mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-15 01:09:20 +02:00
Transport: Remove QUIC (#3754)
https://github.com/XTLS/Xray-core/pull/3554#issuecomment-2236171077
This commit is contained in:
parent
ab3c00e96b
commit
9a953c070f
|
@ -13,7 +13,6 @@ type TransportConfig struct {
|
||||||
WSConfig *WebSocketConfig `json:"wsSettings"`
|
WSConfig *WebSocketConfig `json:"wsSettings"`
|
||||||
HTTPConfig *HTTPConfig `json:"httpSettings"`
|
HTTPConfig *HTTPConfig `json:"httpSettings"`
|
||||||
DSConfig *DomainSocketConfig `json:"dsSettings"`
|
DSConfig *DomainSocketConfig `json:"dsSettings"`
|
||||||
QUICConfig *QUICConfig `json:"quicSettings"`
|
|
||||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||||
HTTPUPGRADEConfig *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
HTTPUPGRADEConfig *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||||
|
@ -79,17 +78,6 @@ func (c *TransportConfig) Build() (*global.Config, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.QUICConfig != nil {
|
|
||||||
qs, err := c.QUICConfig.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed to build QUIC config.").Base(err)
|
|
||||||
}
|
|
||||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
Settings: serial.ToTypedMessage(qs),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GRPCConfig == nil {
|
if c.GRPCConfig == nil {
|
||||||
c.GRPCConfig = c.GUNConfig
|
c.GRPCConfig = c.GUNConfig
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/domainsocket"
|
"github.com/xtls/xray-core/transport/internet/domainsocket"
|
||||||
|
@ -22,7 +21,6 @@ import (
|
||||||
"github.com/xtls/xray-core/transport/internet/http"
|
"github.com/xtls/xray-core/transport/internet/http"
|
||||||
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/quic"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/splithttp"
|
"github.com/xtls/xray-core/transport/internet/splithttp"
|
||||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
|
@ -315,47 +313,6 @@ func (c *HTTPConfig) Build() (proto.Message, error) {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type QUICConfig struct {
|
|
||||||
Header json.RawMessage `json:"header"`
|
|
||||||
Security string `json:"security"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build implements Buildable.
|
|
||||||
func (c *QUICConfig) Build() (proto.Message, error) {
|
|
||||||
config := &quic.Config{
|
|
||||||
Key: c.Key,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.Header) > 0 {
|
|
||||||
headerConfig, _, err := kcpHeaderLoader.Load(c.Header)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("invalid QUIC header config.").Base(err).AtError()
|
|
||||||
}
|
|
||||||
ts, err := headerConfig.(Buildable).Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("invalid QUIC header config").Base(err).AtError()
|
|
||||||
}
|
|
||||||
config.Header = serial.ToTypedMessage(ts)
|
|
||||||
}
|
|
||||||
|
|
||||||
var st protocol.SecurityType
|
|
||||||
switch strings.ToLower(c.Security) {
|
|
||||||
case "aes-128-gcm":
|
|
||||||
st = protocol.SecurityType_AES128_GCM
|
|
||||||
case "chacha20-poly1305":
|
|
||||||
st = protocol.SecurityType_CHACHA20_POLY1305
|
|
||||||
default:
|
|
||||||
st = protocol.SecurityType_NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Security = &protocol.SecurityConfig{
|
|
||||||
Type: st,
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainSocketConfig struct {
|
type DomainSocketConfig struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Abstract bool `json:"abstract"`
|
Abstract bool `json:"abstract"`
|
||||||
|
@ -691,8 +648,6 @@ func (p TransportProtocol) Build() (string, error) {
|
||||||
return "http", nil
|
return "http", nil
|
||||||
case "ds", "domainsocket":
|
case "ds", "domainsocket":
|
||||||
return "domainsocket", nil
|
return "domainsocket", nil
|
||||||
case "quic":
|
|
||||||
return "quic", nil
|
|
||||||
case "grpc", "gun":
|
case "grpc", "gun":
|
||||||
return "grpc", nil
|
return "grpc", nil
|
||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
|
@ -829,7 +784,6 @@ type StreamConfig struct {
|
||||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
|
||||||
SocketSettings *SocketConfig `json:"sockopt"`
|
SocketSettings *SocketConfig `json:"sockopt"`
|
||||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||||
|
@ -932,16 +886,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||||
Settings: serial.ToTypedMessage(ds),
|
Settings: serial.ToTypedMessage(ds),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if c.QUICSettings != nil {
|
|
||||||
qs, err := c.QUICSettings.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed to build QUIC config").Base(err)
|
|
||||||
}
|
|
||||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
Settings: serial.ToTypedMessage(qs),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if c.GRPCConfig == nil {
|
if c.GRPCConfig == nil {
|
||||||
c.GRPCConfig = c.GUNConfig
|
c.GRPCConfig = c.GUNConfig
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
. "github.com/xtls/xray-core/infra/conf"
|
. "github.com/xtls/xray-core/infra/conf"
|
||||||
"github.com/xtls/xray-core/transport/global"
|
"github.com/xtls/xray-core/transport/global"
|
||||||
|
@ -12,9 +11,7 @@ import (
|
||||||
"github.com/xtls/xray-core/transport/internet/grpc"
|
"github.com/xtls/xray-core/transport/internet/grpc"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/http"
|
"github.com/xtls/xray-core/transport/internet/headers/http"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/noop"
|
"github.com/xtls/xray-core/transport/internet/headers/noop"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/tls"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/quic"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
@ -203,12 +200,6 @@ func TestTransportConfig(t *testing.T) {
|
||||||
"wsSettings": {
|
"wsSettings": {
|
||||||
"path": "/t"
|
"path": "/t"
|
||||||
},
|
},
|
||||||
"quicSettings": {
|
|
||||||
"key": "abcd",
|
|
||||||
"header": {
|
|
||||||
"type": "dtls"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grpcSettings": {
|
"grpcSettings": {
|
||||||
"serviceName": "name",
|
"serviceName": "name",
|
||||||
"multiMode": true
|
"multiMode": true
|
||||||
|
@ -272,16 +263,6 @@ func TestTransportConfig(t *testing.T) {
|
||||||
Path: "/t",
|
Path: "/t",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
Settings: serial.ToTypedMessage(&quic.Config{
|
|
||||||
Key: "abcd",
|
|
||||||
Security: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_NONE,
|
|
||||||
},
|
|
||||||
Header: serial.ToTypedMessage(&tls.PacketConfig{}),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
ProtocolName: "grpc",
|
ProtocolName: "grpc",
|
||||||
Settings: serial.ToTypedMessage(&grpc.Config{
|
Settings: serial.ToTypedMessage(&grpc.Config{
|
||||||
|
|
|
@ -55,7 +55,6 @@ import (
|
||||||
_ "github.com/xtls/xray-core/transport/internet/http"
|
_ "github.com/xtls/xray-core/transport/internet/http"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/httpupgrade"
|
_ "github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/kcp"
|
_ "github.com/xtls/xray-core/transport/internet/kcp"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/quic"
|
|
||||||
_ "github.com/xtls/xray-core/transport/internet/reality"
|
_ "github.com/xtls/xray-core/transport/internet/reality"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/splithttp"
|
_ "github.com/xtls/xray-core/transport/internet/splithttp"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/tcp"
|
_ "github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
|
|
|
@ -6,10 +6,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/log"
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
clog "github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
@ -21,14 +19,10 @@ import (
|
||||||
"github.com/xtls/xray-core/proxy/vmess/inbound"
|
"github.com/xtls/xray-core/proxy/vmess/inbound"
|
||||||
"github.com/xtls/xray-core/proxy/vmess/outbound"
|
"github.com/xtls/xray-core/proxy/vmess/outbound"
|
||||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
"github.com/xtls/xray-core/testing/servers/udp"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/domainsocket"
|
"github.com/xtls/xray-core/transport/internet/domainsocket"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/http"
|
"github.com/xtls/xray-core/transport/internet/headers/http"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/wechat"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/quic"
|
|
||||||
tcptransport "github.com/xtls/xray-core/transport/internet/tcp"
|
tcptransport "github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHTTPConnectionHeader(t *testing.T) {
|
func TestHTTPConnectionHeader(t *testing.T) {
|
||||||
|
@ -248,136 +242,3 @@ func TestDomainSocket(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessQuic(t *testing.T) {
|
|
||||||
tcpServer := tcp.Server{
|
|
||||||
MsgProcessor: xor,
|
|
||||||
}
|
|
||||||
dest, err := tcpServer.Start()
|
|
||||||
common.Must(err)
|
|
||||||
defer tcpServer.Close()
|
|
||||||
|
|
||||||
userID := protocol.NewID(uuid.New())
|
|
||||||
serverPort := udp.PickPort()
|
|
||||||
serverConfig := &core.Config{
|
|
||||||
App: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&log.Config{
|
|
||||||
ErrorLogLevel: clog.Severity_Debug,
|
|
||||||
ErrorLogType: log.LogType_Console,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
StreamSettings: &internet.StreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
TransportSettings: []*internet.TransportConfig{
|
|
||||||
{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
Settings: serial.ToTypedMessage(&quic.Config{
|
|
||||||
Header: serial.ToTypedMessage(&wechat.VideoConfig{}),
|
|
||||||
Security: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_NONE,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
clientPort := tcp.PickPort()
|
|
||||||
clientConfig := &core.Config{
|
|
||||||
App: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&log.Config{
|
|
||||||
ErrorLogLevel: clog.Severity_Debug,
|
|
||||||
ErrorLogType: log.LogType_Console,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
|
||||||
Address: net.NewIPOrDomain(dest.Address),
|
|
||||||
Port: uint32(dest.Port),
|
|
||||||
NetworkList: &net.NetworkList{
|
|
||||||
Network: []net.Network{net.Network_TCP},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
|
||||||
{
|
|
||||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
|
||||||
StreamSettings: &internet.StreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
TransportSettings: []*internet.TransportConfig{
|
|
||||||
{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
Settings: serial.ToTypedMessage(&quic.Config{
|
|
||||||
Header: serial.ToTypedMessage(&wechat.VideoConfig{}),
|
|
||||||
Security: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_NONE,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
|
||||||
{
|
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
Port: uint32(serverPort),
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
|
||||||
Id: userID.String(),
|
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
|
||||||
}
|
|
||||||
defer CloseAllServers(servers)
|
|
||||||
|
|
||||||
var errg errgroup.Group
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := errg.Wait(); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/sha256"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getAuth(config *Config) (cipher.AEAD, error) {
|
|
||||||
security := config.Security.GetSecurityType()
|
|
||||||
if security == protocol.SecurityType_NONE {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
salted := []byte(config.Key + "xray-quic-salt")
|
|
||||||
key := sha256.Sum256(salted)
|
|
||||||
|
|
||||||
if security == protocol.SecurityType_AES128_GCM {
|
|
||||||
block, err := aes.NewCipher(key[:16])
|
|
||||||
common.Must(err)
|
|
||||||
return cipher.NewGCM(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
if security == protocol.SecurityType_CHACHA20_POLY1305 {
|
|
||||||
return chacha20poly1305.New(key[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("unsupported security type")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHeader(config *Config) (internet.PacketHeader, error) {
|
|
||||||
if config.Header == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := config.Header.GetInstance()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return internet.CreatePacketHeader(msg)
|
|
||||||
}
|
|
|
@ -1,184 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.34.2
|
|
||||||
// protoc v5.27.0
|
|
||||||
// source: transport/internet/quic/config.proto
|
|
||||||
|
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
protocol "github.com/xtls/xray-core/common/protocol"
|
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
|
||||||
Security *protocol.SecurityConfig `protobuf:"bytes,2,opt,name=security,proto3" json:"security,omitempty"`
|
|
||||||
Header *serial.TypedMessage `protobuf:"bytes,3,opt,name=header,proto3" json:"header,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
|
||||||
*x = Config{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_transport_internet_quic_config_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Config) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_transport_internet_quic_config_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_quic_config_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetKey() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Key
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetSecurity() *protocol.SecurityConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.Security
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetHeader() *serial.TypedMessage {
|
|
||||||
if x != nil {
|
|
||||||
return x.Header
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_quic_config_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_transport_internet_quic_config_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x24, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x71, 0x75, 0x69, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
|
||||||
0x71, 0x75, 0x69, 0x63, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72,
|
|
||||||
0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
|
||||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
|
||||||
0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
|
||||||
0x6b, 0x65, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18,
|
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x63,
|
|
||||||
0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x65, 0x63,
|
|
||||||
0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x38, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18,
|
|
||||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64,
|
|
||||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42,
|
|
||||||
0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x71,
|
|
||||||
0x75, 0x69, 0x63, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
|
||||||
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
|
||||||
0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
|
||||||
0x6e, 0x65, 0x74, 0x2f, 0x71, 0x75, 0x69, 0x63, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
|
||||||
0x65, 0x74, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_transport_internet_quic_config_proto_rawDescOnce sync.Once
|
|
||||||
file_transport_internet_quic_config_proto_rawDescData = file_transport_internet_quic_config_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_transport_internet_quic_config_proto_rawDescGZIP() []byte {
|
|
||||||
file_transport_internet_quic_config_proto_rawDescOnce.Do(func() {
|
|
||||||
file_transport_internet_quic_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_quic_config_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_transport_internet_quic_config_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_transport_internet_quic_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
|
||||||
var file_transport_internet_quic_config_proto_goTypes = []any{
|
|
||||||
(*Config)(nil), // 0: xray.transport.internet.quic.Config
|
|
||||||
(*protocol.SecurityConfig)(nil), // 1: xray.common.protocol.SecurityConfig
|
|
||||||
(*serial.TypedMessage)(nil), // 2: xray.common.serial.TypedMessage
|
|
||||||
}
|
|
||||||
var file_transport_internet_quic_config_proto_depIdxs = []int32{
|
|
||||||
1, // 0: xray.transport.internet.quic.Config.security:type_name -> xray.common.protocol.SecurityConfig
|
|
||||||
2, // 1: xray.transport.internet.quic.Config.header:type_name -> xray.common.serial.TypedMessage
|
|
||||||
2, // [2:2] is the sub-list for method output_type
|
|
||||||
2, // [2:2] is the sub-list for method input_type
|
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
|
||||||
0, // [0:2] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_transport_internet_quic_config_proto_init() }
|
|
||||||
func file_transport_internet_quic_config_proto_init() {
|
|
||||||
if File_transport_internet_quic_config_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_transport_internet_quic_config_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
|
||||||
switch v := v.(*Config); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_transport_internet_quic_config_proto_rawDesc,
|
|
||||||
NumEnums: 0,
|
|
||||||
NumMessages: 1,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_transport_internet_quic_config_proto_goTypes,
|
|
||||||
DependencyIndexes: file_transport_internet_quic_config_proto_depIdxs,
|
|
||||||
MessageInfos: file_transport_internet_quic_config_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_transport_internet_quic_config_proto = out.File
|
|
||||||
file_transport_internet_quic_config_proto_rawDesc = nil
|
|
||||||
file_transport_internet_quic_config_proto_goTypes = nil
|
|
||||||
file_transport_internet_quic_config_proto_depIdxs = nil
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.transport.internet.quic;
|
|
||||||
option csharp_namespace = "Xray.Transport.Internet.Quic";
|
|
||||||
option go_package = "github.com/xtls/xray-core/transport/internet/quic";
|
|
||||||
option java_package = "com.xray.transport.internet.quic";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
import "common/serial/typed_message.proto";
|
|
||||||
import "common/protocol/headers.proto";
|
|
||||||
|
|
||||||
message Config {
|
|
||||||
string key = 1;
|
|
||||||
xray.common.protocol.SecurityConfig security = 2;
|
|
||||||
xray.common.serial.TypedMessage header = 3;
|
|
||||||
}
|
|
|
@ -1,198 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sysConn struct {
|
|
||||||
conn *net.UDPConn
|
|
||||||
header internet.PacketHeader
|
|
||||||
auth cipher.AEAD
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrapSysConn(rawConn *net.UDPConn, config *Config) (*sysConn, error) {
|
|
||||||
header, err := getHeader(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
auth, err := getAuth(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &sysConn{
|
|
||||||
conn: rawConn,
|
|
||||||
header: header,
|
|
||||||
auth: auth,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidPacket = errors.New("invalid packet")
|
|
||||||
|
|
||||||
func (c *sysConn) readFromInternal(p []byte) (int, net.Addr, error) {
|
|
||||||
buffer := getBuffer()
|
|
||||||
defer putBuffer(buffer)
|
|
||||||
|
|
||||||
nBytes, addr, err := c.conn.ReadFrom(buffer)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
payload := buffer[:nBytes]
|
|
||||||
if c.header != nil {
|
|
||||||
if len(payload) <= int(c.header.Size()) {
|
|
||||||
return 0, nil, errInvalidPacket
|
|
||||||
}
|
|
||||||
payload = payload[c.header.Size():]
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.auth == nil {
|
|
||||||
n := copy(p, payload)
|
|
||||||
return n, addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(payload) <= c.auth.NonceSize() {
|
|
||||||
return 0, nil, errInvalidPacket
|
|
||||||
}
|
|
||||||
|
|
||||||
nonce := payload[:c.auth.NonceSize()]
|
|
||||||
payload = payload[c.auth.NonceSize():]
|
|
||||||
|
|
||||||
p, err = c.auth.Open(p[:0], nonce, payload, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nil, errInvalidPacket
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(p), addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) ReadFrom(p []byte) (int, net.Addr, error) {
|
|
||||||
if c.header == nil && c.auth == nil {
|
|
||||||
return c.conn.ReadFrom(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
n, addr, err := c.readFromInternal(p)
|
|
||||||
if err != nil && err != errInvalidPacket {
|
|
||||||
return 0, nil, err
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
return n, addr, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
|
||||||
if c.header == nil && c.auth == nil {
|
|
||||||
return c.conn.WriteTo(p, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := getBuffer()
|
|
||||||
defer putBuffer(buffer)
|
|
||||||
|
|
||||||
payload := buffer
|
|
||||||
n := 0
|
|
||||||
if c.header != nil {
|
|
||||||
c.header.Serialize(payload)
|
|
||||||
n = int(c.header.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.auth == nil {
|
|
||||||
nBytes := copy(payload[n:], p)
|
|
||||||
n += nBytes
|
|
||||||
} else {
|
|
||||||
nounce := payload[n : n+c.auth.NonceSize()]
|
|
||||||
common.Must2(rand.Read(nounce))
|
|
||||||
n += c.auth.NonceSize()
|
|
||||||
pp := c.auth.Seal(payload[:n], nounce, p, nil)
|
|
||||||
n = len(pp)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.conn.WriteTo(payload[:n], addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) Close() error {
|
|
||||||
return c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) LocalAddr() net.Addr {
|
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SetReadBuffer(bytes int) error {
|
|
||||||
return c.conn.SetReadBuffer(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SetWriteBuffer(bytes int) error {
|
|
||||||
return c.conn.SetWriteBuffer(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sysConn) SyscallConn() (syscall.RawConn, error) {
|
|
||||||
return c.conn.SyscallConn()
|
|
||||||
}
|
|
||||||
|
|
||||||
type interConn struct {
|
|
||||||
stream quic.Stream
|
|
||||||
local net.Addr
|
|
||||||
remote net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) Read(b []byte) (int, error) {
|
|
||||||
return c.stream.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|
||||||
mb = buf.Compact(mb)
|
|
||||||
mb, err := buf.WriteMultiBuffer(c, mb)
|
|
||||||
buf.ReleaseMulti(mb)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) Write(b []byte) (int, error) {
|
|
||||||
return c.stream.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) Close() error {
|
|
||||||
return c.stream.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) LocalAddr() net.Addr {
|
|
||||||
return c.local
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) RemoteAddr() net.Addr {
|
|
||||||
return c.remote
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.stream.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.stream.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *interConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.stream.SetWriteDeadline(t)
|
|
||||||
}
|
|
|
@ -1,236 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
|
||||||
"github.com/quic-go/quic-go/logging"
|
|
||||||
"github.com/quic-go/quic-go/qlog"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/task"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
type connectionContext struct {
|
|
||||||
rawConn *sysConn
|
|
||||||
conn quic.Connection
|
|
||||||
}
|
|
||||||
|
|
||||||
var errConnectionClosed = errors.New("connection closed")
|
|
||||||
|
|
||||||
func (c *connectionContext) openStream(destAddr net.Addr) (*interConn, error) {
|
|
||||||
if !isActive(c.conn) {
|
|
||||||
return nil, errConnectionClosed
|
|
||||||
}
|
|
||||||
|
|
||||||
stream, err := c.conn.OpenStream()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := &interConn{
|
|
||||||
stream: stream,
|
|
||||||
local: c.conn.LocalAddr(),
|
|
||||||
remote: destAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientConnections struct {
|
|
||||||
access sync.Mutex
|
|
||||||
conns map[net.Destination][]*connectionContext
|
|
||||||
cleanup *task.Periodic
|
|
||||||
}
|
|
||||||
|
|
||||||
func isActive(s quic.Connection) bool {
|
|
||||||
select {
|
|
||||||
case <-s.Context().Done():
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeInactiveConnections(conns []*connectionContext) []*connectionContext {
|
|
||||||
activeConnections := make([]*connectionContext, 0, len(conns))
|
|
||||||
for i, s := range conns {
|
|
||||||
if isActive(s.conn) {
|
|
||||||
activeConnections = append(activeConnections, s)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogInfo(context.Background(), "closing quic connection at index: ", i)
|
|
||||||
if err := s.conn.CloseWithError(0, ""); err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to close connection")
|
|
||||||
}
|
|
||||||
if err := s.rawConn.Close(); err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to close raw connection")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(activeConnections) < len(conns) {
|
|
||||||
errors.LogInfo(context.Background(), "active quic connection reduced from ", len(conns), " to ", len(activeConnections))
|
|
||||||
return activeConnections
|
|
||||||
}
|
|
||||||
|
|
||||||
return conns
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientConnections) cleanConnections() error {
|
|
||||||
s.access.Lock()
|
|
||||||
defer s.access.Unlock()
|
|
||||||
|
|
||||||
if len(s.conns) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
newConnMap := make(map[net.Destination][]*connectionContext)
|
|
||||||
|
|
||||||
for dest, conns := range s.conns {
|
|
||||||
conns = removeInactiveConnections(conns)
|
|
||||||
if len(conns) > 0 {
|
|
||||||
newConnMap[dest] = conns
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.conns = newConnMap
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientConnections) openConnection(ctx context.Context, destAddr net.Addr, config *Config, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (stat.Connection, error) {
|
|
||||||
s.access.Lock()
|
|
||||||
defer s.access.Unlock()
|
|
||||||
|
|
||||||
if s.conns == nil {
|
|
||||||
s.conns = make(map[net.Destination][]*connectionContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
dest := net.DestinationFromAddr(destAddr)
|
|
||||||
|
|
||||||
var conns []*connectionContext
|
|
||||||
if s, found := s.conns[dest]; found {
|
|
||||||
conns = s
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(conns) > 0 {
|
|
||||||
s := conns[len(conns)-1]
|
|
||||||
if isActive(s.conn) {
|
|
||||||
conn, err := s.openStream(destAddr)
|
|
||||||
if err == nil {
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
errors.LogInfoInner(ctx, err, "failed to openStream: ")
|
|
||||||
} else {
|
|
||||||
errors.LogInfo(ctx, "current quic connection is not active!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conns = removeInactiveConnections(conns)
|
|
||||||
errors.LogInfo(ctx, "dialing quic to ", dest)
|
|
||||||
rawConn, err := internet.DialSystem(ctx, dest, sockopt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
|
||||||
KeepAlivePeriod: 0,
|
|
||||||
HandshakeIdleTimeout: time.Second * 8,
|
|
||||||
MaxIdleTimeout: time.Second * 300,
|
|
||||||
Tracer: func(ctx context.Context, p logging.Perspective, ci quic.ConnectionID) *logging.ConnectionTracer {
|
|
||||||
return qlog.NewConnectionTracer(&QlogWriter{connID: ci}, p, ci)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var udpConn *net.UDPConn
|
|
||||||
switch conn := rawConn.(type) {
|
|
||||||
case *net.UDPConn:
|
|
||||||
udpConn = conn
|
|
||||||
case *internet.PacketConnWrapper:
|
|
||||||
udpConn = conn.Conn.(*net.UDPConn)
|
|
||||||
default:
|
|
||||||
// TODO: Support sockopt for QUIC
|
|
||||||
rawConn.Close()
|
|
||||||
return nil, errors.New("QUIC with sockopt is unsupported").AtWarning()
|
|
||||||
}
|
|
||||||
|
|
||||||
sysConn, err := wrapSysConn(udpConn, config)
|
|
||||||
if err != nil {
|
|
||||||
rawConn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tr := quic.Transport{
|
|
||||||
ConnectionIDLength: 12,
|
|
||||||
Conn: sysConn,
|
|
||||||
}
|
|
||||||
conn, err := tr.Dial(context.Background(), destAddr, tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig)
|
|
||||||
if err != nil {
|
|
||||||
sysConn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
context := &connectionContext{
|
|
||||||
conn: conn,
|
|
||||||
rawConn: sysConn,
|
|
||||||
}
|
|
||||||
s.conns[dest] = append(conns, context)
|
|
||||||
return context.openStream(destAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
var client clientConnections
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
client.conns = make(map[net.Destination][]*connectionContext)
|
|
||||||
client.cleanup = &task.Periodic{
|
|
||||||
Interval: time.Minute,
|
|
||||||
Execute: client.cleanConnections,
|
|
||||||
}
|
|
||||||
common.Must(client.cleanup.Start())
|
|
||||||
}
|
|
||||||
|
|
||||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
|
||||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
|
||||||
if tlsConfig == nil {
|
|
||||||
tlsConfig = &tls.Config{
|
|
||||||
ServerName: internalDomain,
|
|
||||||
AllowInsecure: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var destAddr *net.UDPAddr
|
|
||||||
if dest.Address.Family().IsIP() {
|
|
||||||
destAddr = &net.UDPAddr{
|
|
||||||
IP: dest.Address.IP(),
|
|
||||||
Port: int(dest.Port),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dialerIp := internet.DestIpAddress()
|
|
||||||
if dialerIp != nil {
|
|
||||||
destAddr = &net.UDPAddr{
|
|
||||||
IP: dialerIp,
|
|
||||||
Port: int(dest.Port),
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "quic Dial use dialer dest addr: ", destAddr)
|
|
||||||
} else {
|
|
||||||
addr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
destAddr = addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config := streamSettings.ProtocolSettings.(*Config)
|
|
||||||
|
|
||||||
return client.openConnection(ctx, destAddr, config, tlsConfig, streamSettings.SocketSettings)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
|
||||||
"github.com/quic-go/quic-go/logging"
|
|
||||||
"github.com/quic-go/quic-go/qlog"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Listener is an internet.Listener that listens for TCP connections.
|
|
||||||
type Listener struct {
|
|
||||||
rawConn *sysConn
|
|
||||||
listener *quic.Listener
|
|
||||||
done *done.Instance
|
|
||||||
addConn internet.ConnHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Listener) acceptStreams(conn quic.Connection) {
|
|
||||||
for {
|
|
||||||
stream, err := conn.AcceptStream(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to accept stream")
|
|
||||||
select {
|
|
||||||
case <-conn.Context().Done():
|
|
||||||
return
|
|
||||||
case <-l.done.Wait():
|
|
||||||
if err := conn.CloseWithError(0, ""); err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to close connection")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := &interConn{
|
|
||||||
stream: stream,
|
|
||||||
local: conn.LocalAddr(),
|
|
||||||
remote: conn.RemoteAddr(),
|
|
||||||
}
|
|
||||||
|
|
||||||
l.addConn(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Listener) keepAccepting() {
|
|
||||||
for {
|
|
||||||
conn, err := l.listener.Accept(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to accept QUIC connection")
|
|
||||||
if l.done.Done() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
go l.acceptStreams(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Addr implements internet.Listener.Addr.
|
|
||||||
func (l *Listener) Addr() net.Addr {
|
|
||||||
return l.listener.Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close implements internet.Listener.Close.
|
|
||||||
func (l *Listener) Close() error {
|
|
||||||
l.done.Close()
|
|
||||||
l.listener.Close()
|
|
||||||
l.rawConn.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen creates a new Listener based on configurations.
|
|
||||||
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
|
||||||
if address.Family().IsDomain() {
|
|
||||||
return nil, errors.New("domain address is not allows for listening quic")
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
|
||||||
if tlsConfig == nil {
|
|
||||||
tlsConfig = &tls.Config{
|
|
||||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.DNSNames(internalDomain), cert.CommonName(internalDomain)))},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config := streamSettings.ProtocolSettings.(*Config)
|
|
||||||
rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
|
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
|
||||||
KeepAlivePeriod: 0,
|
|
||||||
HandshakeIdleTimeout: time.Second * 8,
|
|
||||||
MaxIdleTimeout: time.Second * 300,
|
|
||||||
MaxIncomingStreams: 32,
|
|
||||||
MaxIncomingUniStreams: -1,
|
|
||||||
Tracer: func(ctx context.Context, p logging.Perspective, ci quic.ConnectionID) *logging.ConnectionTracer {
|
|
||||||
return qlog.NewConnectionTracer(&QlogWriter{connID: ci}, p, ci)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := wrapSysConn(rawConn.(*net.UDPConn), config)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tr := quic.Transport{
|
|
||||||
ConnectionIDLength: 12,
|
|
||||||
Conn: conn,
|
|
||||||
}
|
|
||||||
qListener, err := tr.Listen(tlsConfig.GetTLSConfig(), quicConfig)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
listener := &Listener{
|
|
||||||
done: done.New(),
|
|
||||||
rawConn: conn,
|
|
||||||
listener: qListener,
|
|
||||||
addConn: handler,
|
|
||||||
}
|
|
||||||
|
|
||||||
go listener.keepAccepting()
|
|
||||||
|
|
||||||
return listener, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
common.Must(internet.RegisterTransportListener(protocolName, Listen))
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/bytespool"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pool *sync.Pool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
pool = bytespool.GetPool(2048)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBuffer() []byte {
|
|
||||||
return pool.Get().([]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
func putBuffer(p []byte) {
|
|
||||||
pool.Put(p)
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import "github.com/quic-go/quic-go"
|
|
||||||
|
|
||||||
type QlogWriter struct {
|
|
||||||
connID quic.ConnectionID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *QlogWriter) Write(b []byte) (int, error) {
|
|
||||||
// to much log, only turn on when debug Quic
|
|
||||||
|
|
||||||
// if len(b) > 1 { // skip line separator "0a" in qlog
|
|
||||||
// log.Record(&log.GeneralMessage{
|
|
||||||
// Severity: log.Severity_Debug,
|
|
||||||
// Content: fmt.Sprintf("[%x] %s", w.connID, b),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
return len(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *QlogWriter) Close() error {
|
|
||||||
// Noop
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package quic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
||||||
|
|
||||||
// Here is some modification needs to be done before update quic vendor.
|
|
||||||
// * use bytespool in buffer_pool.go
|
|
||||||
// * set MaxReceivePacketSize to 1452 - 32 (16 bytes auth, 16 bytes head)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
const (
|
|
||||||
protocolName = "quic"
|
|
||||||
internalDomain = "quic.internal.example.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
|
||||||
return new(Config)
|
|
||||||
}))
|
|
||||||
}
|
|
|
@ -1,223 +0,0 @@
|
||||||
package quic_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/testing/servers/udp"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/wireguard"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/quic"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestQuicConnection(t *testing.T) {
|
|
||||||
port := udp.PickPort()
|
|
||||||
|
|
||||||
listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{},
|
|
||||||
SecurityType: "tls",
|
|
||||||
SecuritySettings: &tls.Config{
|
|
||||||
Certificate: []*tls.Certificate{
|
|
||||||
tls.ParseCertificate(
|
|
||||||
cert.MustGenerate(nil,
|
|
||||||
cert.DNSNames("www.example.com"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, func(conn stat.Connection) {
|
|
||||||
go func() {
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
b := buf.New()
|
|
||||||
defer b.Release()
|
|
||||||
|
|
||||||
for {
|
|
||||||
b.Clear()
|
|
||||||
if _, err := b.ReadFrom(conn); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
common.Must2(conn.Write(b.Bytes()))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
defer listener.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
dctx := context.Background()
|
|
||||||
conn, err := quic.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{},
|
|
||||||
SecurityType: "tls",
|
|
||||||
SecuritySettings: &tls.Config{
|
|
||||||
ServerName: "www.example.com",
|
|
||||||
AllowInsecure: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
const N = 1024
|
|
||||||
b1 := make([]byte, N)
|
|
||||||
common.Must2(rand.Read(b1))
|
|
||||||
b2 := buf.New()
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestQuicConnectionWithoutTLS(t *testing.T) {
|
|
||||||
port := udp.PickPort()
|
|
||||||
|
|
||||||
listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{},
|
|
||||||
}, func(conn stat.Connection) {
|
|
||||||
go func() {
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
b := buf.New()
|
|
||||||
defer b.Release()
|
|
||||||
|
|
||||||
for {
|
|
||||||
b.Clear()
|
|
||||||
if _, err := b.ReadFrom(conn); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
common.Must2(conn.Write(b.Bytes()))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
defer listener.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
dctx := context.Background()
|
|
||||||
conn, err := quic.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{},
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
const N = 1024
|
|
||||||
b1 := make([]byte, N)
|
|
||||||
common.Must2(rand.Read(b1))
|
|
||||||
b2 := buf.New()
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestQuicConnectionAuthHeader(t *testing.T) {
|
|
||||||
port := udp.PickPort()
|
|
||||||
|
|
||||||
listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{
|
|
||||||
Header: serial.ToTypedMessage(&wireguard.WireguardConfig{}),
|
|
||||||
Key: "abcd",
|
|
||||||
Security: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, func(conn stat.Connection) {
|
|
||||||
go func() {
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
b := buf.New()
|
|
||||||
defer b.Release()
|
|
||||||
|
|
||||||
for {
|
|
||||||
b.Clear()
|
|
||||||
if _, err := b.ReadFrom(conn); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
common.Must2(conn.Write(b.Bytes()))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
defer listener.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
dctx := context.Background()
|
|
||||||
conn, err := quic.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
|
||||||
ProtocolName: "quic",
|
|
||||||
ProtocolSettings: &quic.Config{
|
|
||||||
Header: serial.ToTypedMessage(&wireguard.WireguardConfig{}),
|
|
||||||
Key: "abcd",
|
|
||||||
Security: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
const N = 1024
|
|
||||||
b1 := make([]byte, N)
|
|
||||||
common.Must2(rand.Read(b1))
|
|
||||||
b2 := buf.New()
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Must2(conn.Write(b1))
|
|
||||||
|
|
||||||
b2.Clear()
|
|
||||||
common.Must2(b2.ReadFullFrom(conn, N))
|
|
||||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue