github.com/sagernet/sing-box@v1.9.0-rc.20/transport/v2raygrpc/server.go (about)

     1  package v2raygrpc
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"os"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/sagernet/sing-box/adapter"
    11  	"github.com/sagernet/sing-box/common/tls"
    12  	"github.com/sagernet/sing-box/option"
    13  	"github.com/sagernet/sing/common"
    14  	M "github.com/sagernet/sing/common/metadata"
    15  	N "github.com/sagernet/sing/common/network"
    16  
    17  	"golang.org/x/net/http2"
    18  	"google.golang.org/grpc"
    19  	"google.golang.org/grpc/keepalive"
    20  	gM "google.golang.org/grpc/metadata"
    21  	"google.golang.org/grpc/peer"
    22  )
    23  
    24  var _ adapter.V2RayServerTransport = (*Server)(nil)
    25  
    26  type Server struct {
    27  	ctx     context.Context
    28  	handler N.TCPConnectionHandler
    29  	server  *grpc.Server
    30  }
    31  
    32  func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler) (*Server, error) {
    33  	var serverOptions []grpc.ServerOption
    34  	if tlsConfig != nil {
    35  		if !common.Contains(tlsConfig.NextProtos(), http2.NextProtoTLS) {
    36  			tlsConfig.SetNextProtos(append([]string{"h2"}, tlsConfig.NextProtos()...))
    37  		}
    38  		serverOptions = append(serverOptions, grpc.Creds(NewTLSTransportCredentials(tlsConfig)))
    39  	}
    40  	if options.IdleTimeout > 0 {
    41  		serverOptions = append(serverOptions, grpc.KeepaliveParams(keepalive.ServerParameters{
    42  			Time:    time.Duration(options.IdleTimeout),
    43  			Timeout: time.Duration(options.PingTimeout),
    44  		}))
    45  	}
    46  	server := &Server{ctx, handler, grpc.NewServer(serverOptions...)}
    47  	RegisterGunServiceCustomNameServer(server.server, server, options.ServiceName)
    48  	return server, nil
    49  }
    50  
    51  func (s *Server) Tun(server GunService_TunServer) error {
    52  	ctx, cancel := common.ContextWithCancelCause(s.ctx)
    53  	conn := NewGRPCConn(server, cancel)
    54  	var metadata M.Metadata
    55  	if remotePeer, loaded := peer.FromContext(server.Context()); loaded {
    56  		metadata.Source = M.SocksaddrFromNet(remotePeer.Addr)
    57  	}
    58  	if grpcMetadata, loaded := gM.FromIncomingContext(server.Context()); loaded {
    59  		forwardFrom := strings.Join(grpcMetadata.Get("X-Forwarded-For"), ",")
    60  		if forwardFrom != "" {
    61  			for _, from := range strings.Split(forwardFrom, ",") {
    62  				originAddr := M.ParseSocksaddr(from)
    63  				if originAddr.IsValid() {
    64  					metadata.Source = originAddr.Unwrap()
    65  				}
    66  			}
    67  		}
    68  	}
    69  	go s.handler.NewConnection(ctx, conn, metadata)
    70  	<-ctx.Done()
    71  	return nil
    72  }
    73  
    74  func (s *Server) mustEmbedUnimplementedGunServiceServer() {
    75  }
    76  
    77  func (s *Server) Network() []string {
    78  	return []string{N.NetworkTCP}
    79  }
    80  
    81  func (s *Server) Serve(listener net.Listener) error {
    82  	return s.server.Serve(listener)
    83  }
    84  
    85  func (s *Server) ServePacket(listener net.PacketConn) error {
    86  	return os.ErrInvalid
    87  }
    88  
    89  func (s *Server) Close() error {
    90  	s.server.Stop()
    91  	return nil
    92  }