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

     1  package v2raygrpclite
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/http"
     7  	"os"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/sagernet/sing-box/adapter"
    12  	"github.com/sagernet/sing-box/common/tls"
    13  	"github.com/sagernet/sing-box/option"
    14  	"github.com/sagernet/sing-box/transport/v2rayhttp"
    15  	"github.com/sagernet/sing/common"
    16  	E "github.com/sagernet/sing/common/exceptions"
    17  	M "github.com/sagernet/sing/common/metadata"
    18  	N "github.com/sagernet/sing/common/network"
    19  	aTLS "github.com/sagernet/sing/common/tls"
    20  	sHttp "github.com/sagernet/sing/protocol/http"
    21  
    22  	"golang.org/x/net/http2"
    23  	"golang.org/x/net/http2/h2c"
    24  )
    25  
    26  var _ adapter.V2RayServerTransport = (*Server)(nil)
    27  
    28  type Server struct {
    29  	tlsConfig    tls.ServerConfig
    30  	handler      adapter.V2RayServerTransportHandler
    31  	errorHandler E.Handler
    32  	httpServer   *http.Server
    33  	h2Server     *http2.Server
    34  	h2cHandler   http.Handler
    35  	path         string
    36  }
    37  
    38  func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (*Server, error) {
    39  	server := &Server{
    40  		tlsConfig: tlsConfig,
    41  		handler:   handler,
    42  		path:      "/" + options.ServiceName + "/Tun",
    43  		h2Server: &http2.Server{
    44  			IdleTimeout: time.Duration(options.IdleTimeout),
    45  		},
    46  	}
    47  	server.httpServer = &http.Server{
    48  		Handler: server,
    49  		BaseContext: func(net.Listener) context.Context {
    50  			return ctx
    51  		},
    52  	}
    53  	server.h2cHandler = h2c.NewHandler(server, server.h2Server)
    54  	return server, nil
    55  }
    56  
    57  func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    58  	if request.Method == "PRI" && len(request.Header) == 0 && request.URL.Path == "*" && request.Proto == "HTTP/2.0" {
    59  		s.h2cHandler.ServeHTTP(writer, request)
    60  		return
    61  	}
    62  	if request.URL.Path != s.path {
    63  		s.invalidRequest(writer, request, http.StatusNotFound, E.New("bad path: ", request.URL.Path))
    64  		return
    65  	}
    66  	if request.Method != http.MethodPost {
    67  		s.invalidRequest(writer, request, http.StatusNotFound, E.New("bad method: ", request.Method))
    68  		return
    69  	}
    70  	if ct := request.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/grpc") {
    71  		s.invalidRequest(writer, request, http.StatusNotFound, E.New("bad content type: ", ct))
    72  		return
    73  	}
    74  	writer.Header().Set("Content-Type", "application/grpc")
    75  	writer.Header().Set("TE", "trailers")
    76  	writer.WriteHeader(http.StatusOK)
    77  	var metadata M.Metadata
    78  	metadata.Source = sHttp.SourceAddress(request)
    79  	conn := v2rayhttp.NewHTTP2Wrapper(newGunConn(request.Body, writer, writer.(http.Flusher)))
    80  	s.handler.NewConnection(request.Context(), conn, metadata)
    81  	conn.CloseWrapper()
    82  }
    83  
    84  func (s *Server) invalidRequest(writer http.ResponseWriter, request *http.Request, statusCode int, err error) {
    85  	if statusCode > 0 {
    86  		writer.WriteHeader(statusCode)
    87  	}
    88  	s.handler.NewError(request.Context(), E.Cause(err, "process connection from ", request.RemoteAddr))
    89  }
    90  
    91  func (s *Server) Network() []string {
    92  	return []string{N.NetworkTCP}
    93  }
    94  
    95  func (s *Server) Serve(listener net.Listener) error {
    96  	if s.tlsConfig != nil {
    97  		if !common.Contains(s.tlsConfig.NextProtos(), http2.NextProtoTLS) {
    98  			s.tlsConfig.SetNextProtos(append([]string{"h2"}, s.tlsConfig.NextProtos()...))
    99  		}
   100  		listener = aTLS.NewListener(listener, s.tlsConfig)
   101  	}
   102  	return s.httpServer.Serve(listener)
   103  }
   104  
   105  func (s *Server) ServePacket(listener net.PacketConn) error {
   106  	return os.ErrInvalid
   107  }
   108  
   109  func (s *Server) Close() error {
   110  	return common.Close(common.PtrOrNil(s.httpServer))
   111  }