Фабрика транспорта V2Ray
Исходный код: transport/v2ray/transport.go, transport/v2ray/quic.go, transport/v2ray/grpc.go, transport/v2ray/grpc_lite.go
Паттерн «Фабрика»
Фабрика транспорта V2Ray использует обобщённые псевдонимы типов и диспетчер на основе type-switch для создания серверных и клиентских транспортов. Это единая точка входа для создания всех транспортов V2Ray.
Обобщённые типы конструкторов
type (
ServerConstructor[O any] func(
ctx context.Context,
logger logger.ContextLogger,
options O,
tlsConfig tls.ServerConfig,
handler adapter.V2RayServerTransportHandler,
) (adapter.V2RayServerTransport, error)
ClientConstructor[O any] func(
ctx context.Context,
dialer N.Dialer,
serverAddr M.Socksaddr,
options O,
tlsConfig tls.Config,
) (adapter.V2RayClientTransport, error)
)Эти обобщённые типы параметризуют структуру опций O, позволяя каждому транспорту определять собственный тип конфигурации, сохраняя при этом общую сигнатуру конструктора.
Диспетчеризация серверного транспорта
func NewServerTransport(ctx context.Context, logger logger.ContextLogger,
options option.V2RayTransportOptions, tlsConfig tls.ServerConfig,
handler adapter.V2RayServerTransportHandler) (adapter.V2RayServerTransport, error) {
if options.Type == "" {
return nil, nil
}
switch options.Type {
case C.V2RayTransportTypeHTTP:
return v2rayhttp.NewServer(ctx, logger, options.HTTPOptions, tlsConfig, handler)
case C.V2RayTransportTypeWebsocket:
return v2raywebsocket.NewServer(ctx, logger, options.WebsocketOptions, tlsConfig, handler)
case C.V2RayTransportTypeQUIC:
if tlsConfig == nil {
return nil, C.ErrTLSRequired
}
return NewQUICServer(ctx, logger, options.QUICOptions, tlsConfig, handler)
case C.V2RayTransportTypeGRPC:
return NewGRPCServer(ctx, logger, options.GRPCOptions, tlsConfig, handler)
case C.V2RayTransportTypeHTTPUpgrade:
return v2rayhttpupgrade.NewServer(ctx, logger, options.HTTPUpgradeOptions, tlsConfig, handler)
default:
return nil, E.New("unknown transport type: " + options.Type)
}
}Ключевые особенности поведения:
- Пустой тип возвращает
nil, nil(транспорт не настроен) - QUIC требует TLS -- возвращает
C.ErrTLSRequired, еслиtlsConfigравен nil - HTTP, WebSocket и HTTP Upgrade импортируются и вызываются напрямую
- gRPC и QUIC диспетчеризуются через промежуточные функции, обрабатывающие переключение по тегам сборки
Диспетчеризация клиентского транспорта
NewClientTransport следует тому же паттерну. Клиентский вариант получает N.Dialer и M.Socksaddr вместо обработчика:
func NewClientTransport(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr,
options option.V2RayTransportOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error)Обратите внимание, что конфигурация TLS -- это tls.Config (клиентский интерфейс) в отличие от tls.ServerConfig (серверный интерфейс).
Паттерн регистрации QUIC
Транспорт QUIC требует тега сборки with_quic. Поскольку основной пакет v2ray не может напрямую импортировать v2rayquic (который может быть не скомпилирован), используется паттерн регистрации:
// quic.go
var (
quicServerConstructor ServerConstructor[option.V2RayQUICOptions]
quicClientConstructor ClientConstructor[option.V2RayQUICOptions]
)
func RegisterQUICConstructor(
server ServerConstructor[option.V2RayQUICOptions],
client ClientConstructor[option.V2RayQUICOptions],
) {
quicServerConstructor = server
quicClientConstructor = client
}
func NewQUICServer(...) (adapter.V2RayServerTransport, error) {
if quicServerConstructor == nil {
return nil, os.ErrInvalid
}
return quicServerConstructor(ctx, logger, options, tlsConfig, handler)
}Пакет v2rayquic регистрирует себя через init():
// v2rayquic/init.go
//go:build with_quic
func init() {
v2ray.RegisterQUICConstructor(NewServer, NewClient)
}Если скомпилировано без with_quic, конструкторы остаются nil, и NewQUICServer/NewQUICClient возвращают os.ErrInvalid.
Переключение gRPC по тегам сборки
gRPC имеет две реализации, управляемые тегами сборки:
С with_grpc (grpc.go):
//go:build with_grpc
func NewGRPCServer(...) (adapter.V2RayServerTransport, error) {
if options.ForceLite {
return v2raygrpclite.NewServer(ctx, logger, options, tlsConfig, handler)
}
return v2raygrpc.NewServer(ctx, logger, options, tlsConfig, handler)
}Когда полная библиотека gRPC доступна, пользователь всё равно может принудительно использовать облегченную реализацию через options.ForceLite.
Без with_grpc (grpc_lite.go):
//go:build !with_grpc
func NewGRPCServer(...) (adapter.V2RayServerTransport, error) {
return v2raygrpclite.NewServer(ctx, logger, options, tlsConfig, handler)
}Без тега сборки облегченная реализация используется всегда, независимо от ForceLite.
Конфигурация
{
"transport": {
"type": "ws",
"path": "/path",
"headers": {
"Host": "example.com"
},
"max_early_data": 2048,
"early_data_header_name": "Sec-WebSocket-Protocol"
}
}Структура V2RayTransportOptions содержит строку Type и подструктуры опций для каждого типа транспорта (HTTPOptions, WebsocketOptions, QUICOptions, GRPCOptions, HTTPUpgradeOptions). Используются только подопции, соответствующие выбранному типу.