mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-25 14:46:04 +03:00
55dc26f228
Now you are able to configure REALITY gRPC client and server Duplicate of REALITY H2, perhaps, just for fun
144 lines
3.9 KiB
Go
144 lines
3.9 KiB
Go
package grpc
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
goreality "github.com/xtls/reality"
|
|
"github.com/xtls/xray-core/common"
|
|
"github.com/xtls/xray-core/common/net"
|
|
"github.com/xtls/xray-core/common/session"
|
|
"github.com/xtls/xray-core/transport/internet"
|
|
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
|
"github.com/xtls/xray-core/transport/internet/reality"
|
|
"github.com/xtls/xray-core/transport/internet/tls"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/keepalive"
|
|
)
|
|
|
|
type Listener struct {
|
|
encoding.UnimplementedGRPCServiceServer
|
|
ctx context.Context
|
|
handler internet.ConnHandler
|
|
local net.Addr
|
|
config *Config
|
|
locker *internet.FileLocker // for unix domain socket
|
|
|
|
s *grpc.Server
|
|
}
|
|
|
|
func (l Listener) Tun(server encoding.GRPCService_TunServer) error {
|
|
tunCtx, cancel := context.WithCancel(l.ctx)
|
|
l.handler(encoding.NewHunkConn(server, cancel))
|
|
<-tunCtx.Done()
|
|
return nil
|
|
}
|
|
|
|
func (l Listener) TunMulti(server encoding.GRPCService_TunMultiServer) error {
|
|
tunCtx, cancel := context.WithCancel(l.ctx)
|
|
l.handler(encoding.NewMultiHunkConn(server, cancel))
|
|
<-tunCtx.Done()
|
|
return nil
|
|
}
|
|
|
|
func (l Listener) Close() error {
|
|
l.s.Stop()
|
|
return nil
|
|
}
|
|
|
|
func (l Listener) Addr() net.Addr {
|
|
return l.local
|
|
}
|
|
|
|
func Listen(ctx context.Context, address net.Address, port net.Port, settings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
|
grpcSettings := settings.ProtocolSettings.(*Config)
|
|
var listener *Listener
|
|
if port == net.Port(0) { // unix
|
|
listener = &Listener{
|
|
handler: handler,
|
|
local: &net.UnixAddr{
|
|
Name: address.Domain(),
|
|
Net: "unix",
|
|
},
|
|
config: grpcSettings,
|
|
}
|
|
} else { // tcp
|
|
listener = &Listener{
|
|
handler: handler,
|
|
local: &net.TCPAddr{
|
|
IP: address.IP(),
|
|
Port: int(port),
|
|
},
|
|
config: grpcSettings,
|
|
}
|
|
}
|
|
|
|
listener.ctx = ctx
|
|
|
|
config := tls.ConfigFromStreamSettings(settings)
|
|
|
|
var options []grpc.ServerOption
|
|
var s *grpc.Server
|
|
if config != nil {
|
|
// gRPC server may silently ignore TLS errors
|
|
options = append(options, grpc.Creds(credentials.NewTLS(config.GetTLSConfig(tls.WithNextProto("h2")))))
|
|
}
|
|
if grpcSettings.IdleTimeout > 0 || grpcSettings.HealthCheckTimeout > 0 {
|
|
options = append(options, grpc.KeepaliveParams(keepalive.ServerParameters{
|
|
Time: time.Second * time.Duration(grpcSettings.IdleTimeout),
|
|
Timeout: time.Second * time.Duration(grpcSettings.HealthCheckTimeout),
|
|
}))
|
|
}
|
|
|
|
s = grpc.NewServer(options...)
|
|
listener.s = s
|
|
|
|
if settings.SocketSettings != nil && settings.SocketSettings.AcceptProxyProtocol {
|
|
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
|
}
|
|
|
|
go func() {
|
|
var streamListener net.Listener
|
|
var err error
|
|
if port == net.Port(0) { // unix
|
|
streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
|
Name: address.Domain(),
|
|
Net: "unix",
|
|
}, settings.SocketSettings)
|
|
if err != nil {
|
|
newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
|
|
return
|
|
}
|
|
locker := ctx.Value(address.Domain())
|
|
if locker != nil {
|
|
listener.locker = locker.(*internet.FileLocker)
|
|
}
|
|
} else { // tcp
|
|
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
|
IP: address.IP(),
|
|
Port: int(port),
|
|
}, settings.SocketSettings)
|
|
if err != nil {
|
|
newError("failed to listen on ", address, ":", port).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
|
|
return
|
|
}
|
|
}
|
|
|
|
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getNormalizedName())
|
|
|
|
if config := reality.ConfigFromStreamSettings(settings); config != nil {
|
|
streamListener = goreality.NewListener(streamListener, config.GetREALITYConfig())
|
|
}
|
|
if err = s.Serve(streamListener); err != nil {
|
|
newError("Listener for gRPC ended").Base(err).WriteToLog()
|
|
}
|
|
}()
|
|
|
|
return listener, nil
|
|
}
|
|
|
|
func init() {
|
|
common.Must(internet.RegisterTransportListener(protocolName, Listen))
|
|
}
|