github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/internal/testutils/fakeserver/server.go (about)

     1  /*
     2   *
     3   * Copyright 2019 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  // Package fakeserver provides a fake implementation of the management server.
    20  package fakeserver
    21  
    22  import (
    23  	"fmt"
    24  	"io"
    25  	"net"
    26  	"time"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  	grpc "github.com/hxx258456/ccgo/grpc"
    30  	"github.com/hxx258456/ccgo/grpc/codes"
    31  	"github.com/hxx258456/ccgo/grpc/internal/testutils"
    32  	"github.com/hxx258456/ccgo/grpc/status"
    33  
    34  	discoverypb "github.com/hxx258456/ccgo/go-control-plane/envoy/api/v2"
    35  	adsgrpc "github.com/hxx258456/ccgo/go-control-plane/envoy/service/discovery/v2"
    36  	lrsgrpc "github.com/hxx258456/ccgo/go-control-plane/envoy/service/load_stats/v2"
    37  	lrspb "github.com/hxx258456/ccgo/go-control-plane/envoy/service/load_stats/v2"
    38  )
    39  
    40  const (
    41  	// TODO: Make this a var or a field in the server if there is a need to use a
    42  	// value other than this default.
    43  	defaultChannelBufferSize = 50
    44  	defaultDialTimeout       = 5 * time.Second
    45  )
    46  
    47  // Request wraps the request protobuf (xds/LRS) and error received by the
    48  // Server in a call to stream.Recv().
    49  type Request struct {
    50  	Req proto.Message
    51  	Err error
    52  }
    53  
    54  // Response wraps the response protobuf (xds/LRS) and error that the Server
    55  // should send out to the client through a call to stream.Send()
    56  type Response struct {
    57  	Resp proto.Message
    58  	Err  error
    59  }
    60  
    61  // Server is a fake implementation of xDS and LRS protocols. It listens on the
    62  // same port for both services and exposes a bunch of channels to send/receive
    63  // messages.
    64  type Server struct {
    65  	// XDSRequestChan is a channel on which received xDS requests are made
    66  	// available to the users of this Server.
    67  	XDSRequestChan *testutils.Channel
    68  	// XDSResponseChan is a channel on which the Server accepts xDS responses
    69  	// to be sent to the client.
    70  	XDSResponseChan chan *Response
    71  	// LRSRequestChan is a channel on which received LRS requests are made
    72  	// available to the users of this Server.
    73  	LRSRequestChan *testutils.Channel
    74  	// LRSResponseChan is a channel on which the Server accepts the LRS
    75  	// response to be sent to the client.
    76  	LRSResponseChan chan *Response
    77  	// NewConnChan is a channel on which the fake server notifies receipt of new
    78  	// connection attempts. Tests can gate on this event before proceeding to
    79  	// other actions which depend on a connection to the fake server being up.
    80  	NewConnChan *testutils.Channel
    81  	// Address is the host:port on which the Server is listening for requests.
    82  	Address string
    83  
    84  	// The underlying fake implementation of xDS and LRS.
    85  	xdsS *xdsServer
    86  	lrsS *lrsServer
    87  }
    88  
    89  type wrappedListener struct {
    90  	net.Listener
    91  	server *Server
    92  }
    93  
    94  func (wl *wrappedListener) Accept() (net.Conn, error) {
    95  	c, err := wl.Listener.Accept()
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	wl.server.NewConnChan.Send(struct{}{})
   100  	return c, err
   101  }
   102  
   103  // StartServer makes a new Server and gets it to start listening on a local
   104  // port for gRPC requests. The returned cancel function should be invoked by
   105  // the caller upon completion of the test.
   106  func StartServer() (*Server, func(), error) {
   107  	lis, err := net.Listen("tcp", "localhost:0")
   108  	if err != nil {
   109  		return nil, func() {}, fmt.Errorf("net.Listen() failed: %v", err)
   110  	}
   111  
   112  	s := &Server{
   113  		XDSRequestChan:  testutils.NewChannelWithSize(defaultChannelBufferSize),
   114  		LRSRequestChan:  testutils.NewChannelWithSize(defaultChannelBufferSize),
   115  		NewConnChan:     testutils.NewChannelWithSize(defaultChannelBufferSize),
   116  		XDSResponseChan: make(chan *Response, defaultChannelBufferSize),
   117  		LRSResponseChan: make(chan *Response, 1), // The server only ever sends one response.
   118  		Address:         lis.Addr().String(),
   119  	}
   120  	s.xdsS = &xdsServer{reqChan: s.XDSRequestChan, respChan: s.XDSResponseChan}
   121  	s.lrsS = &lrsServer{reqChan: s.LRSRequestChan, respChan: s.LRSResponseChan}
   122  	wp := &wrappedListener{
   123  		Listener: lis,
   124  		server:   s,
   125  	}
   126  
   127  	server := grpc.NewServer()
   128  	lrsgrpc.RegisterLoadReportingServiceServer(server, s.lrsS)
   129  	adsgrpc.RegisterAggregatedDiscoveryServiceServer(server, s.xdsS)
   130  	go server.Serve(wp)
   131  
   132  	return s, func() { server.Stop() }, nil
   133  }
   134  
   135  type xdsServer struct {
   136  	reqChan  *testutils.Channel
   137  	respChan chan *Response
   138  }
   139  
   140  func (xdsS *xdsServer) StreamAggregatedResources(s adsgrpc.AggregatedDiscoveryService_StreamAggregatedResourcesServer) error {
   141  	errCh := make(chan error, 2)
   142  	go func() {
   143  		for {
   144  			req, err := s.Recv()
   145  			if err != nil {
   146  				errCh <- err
   147  				return
   148  			}
   149  			xdsS.reqChan.Send(&Request{req, err})
   150  		}
   151  	}()
   152  	go func() {
   153  		var retErr error
   154  		defer func() {
   155  			errCh <- retErr
   156  		}()
   157  
   158  		for {
   159  			select {
   160  			case r := <-xdsS.respChan:
   161  				if r.Err != nil {
   162  					retErr = r.Err
   163  					return
   164  				}
   165  				if err := s.Send(r.Resp.(*discoverypb.DiscoveryResponse)); err != nil {
   166  					retErr = err
   167  					return
   168  				}
   169  			case <-s.Context().Done():
   170  				retErr = s.Context().Err()
   171  				return
   172  			}
   173  		}
   174  	}()
   175  
   176  	if err := <-errCh; err != nil {
   177  		return err
   178  	}
   179  	return nil
   180  }
   181  
   182  func (xdsS *xdsServer) DeltaAggregatedResources(adsgrpc.AggregatedDiscoveryService_DeltaAggregatedResourcesServer) error {
   183  	return status.Error(codes.Unimplemented, "")
   184  }
   185  
   186  type lrsServer struct {
   187  	reqChan  *testutils.Channel
   188  	respChan chan *Response
   189  }
   190  
   191  func (lrsS *lrsServer) StreamLoadStats(s lrsgrpc.LoadReportingService_StreamLoadStatsServer) error {
   192  	req, err := s.Recv()
   193  	lrsS.reqChan.Send(&Request{req, err})
   194  	if err != nil {
   195  		return err
   196  	}
   197  
   198  	select {
   199  	case r := <-lrsS.respChan:
   200  		if r.Err != nil {
   201  			return r.Err
   202  		}
   203  		if err := s.Send(r.Resp.(*lrspb.LoadStatsResponse)); err != nil {
   204  			return err
   205  		}
   206  	case <-s.Context().Done():
   207  		return s.Context().Err()
   208  	}
   209  
   210  	for {
   211  		req, err := s.Recv()
   212  		lrsS.reqChan.Send(&Request{req, err})
   213  		if err != nil {
   214  			if err == io.EOF {
   215  				return nil
   216  			}
   217  			return err
   218  		}
   219  	}
   220  }