github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/grpc/grpc.go (about)

     1  // Copyright 2020 Asim Aslam
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // Original source: github.com/micro/go-micro/v3/server/grpc/grpc.go
    16  
    17  // Package grpc provides a grpc server
    18  package grpc
    19  
    20  import (
    21  	"context"
    22  	"crypto/tls"
    23  	"encoding/base64"
    24  	"encoding/json"
    25  	"fmt"
    26  	"io"
    27  	"net"
    28  	"net/http"
    29  	"reflect"
    30  	"runtime/debug"
    31  	"sort"
    32  	"strconv"
    33  	"strings"
    34  	"sync"
    35  	"time"
    36  
    37  	"github.com/golang/protobuf/proto"
    38  	"github.com/improbable-eng/grpc-web/go/grpcweb"
    39  	pberr "github.com/tickoalcantara12/micro/v3/proto/errors"
    40  	"github.com/tickoalcantara12/micro/v3/service/broker"
    41  	meta "github.com/tickoalcantara12/micro/v3/service/context/metadata"
    42  	"github.com/tickoalcantara12/micro/v3/service/errors"
    43  	"github.com/tickoalcantara12/micro/v3/service/logger"
    44  	"github.com/tickoalcantara12/micro/v3/service/registry"
    45  	"github.com/tickoalcantara12/micro/v3/service/server"
    46  	"github.com/tickoalcantara12/micro/v3/util/addr"
    47  	"github.com/tickoalcantara12/micro/v3/util/backoff"
    48  	mnet "github.com/tickoalcantara12/micro/v3/util/net"
    49  	"golang.org/x/net/http2"
    50  	"golang.org/x/net/netutil"
    51  
    52  	"google.golang.org/grpc"
    53  	"google.golang.org/grpc/codes"
    54  	"google.golang.org/grpc/credentials"
    55  	"google.golang.org/grpc/encoding"
    56  	"google.golang.org/grpc/metadata"
    57  	"google.golang.org/grpc/peer"
    58  	"google.golang.org/grpc/status"
    59  )
    60  
    61  var (
    62  	// DefaultMaxRecvMsgSize maximum message that client can receive
    63  	// (32 MB).
    64  	DefaultMaxRecvMsgSize = 1024 * 1024 * 32
    65  
    66  	// DefaultMaxSendMsgSize maximum message that client can send
    67  	// (32 MB).
    68  	DefaultMaxSendMsgSize = 1024 * 1024 * 32
    69  )
    70  
    71  const (
    72  	defaultContentType = "application/grpc"
    73  )
    74  
    75  type grpcServer struct {
    76  	rpc *rServer
    77  	srv *grpc.Server
    78  
    79  	exit chan chan error
    80  	wg   *sync.WaitGroup
    81  
    82  	sync.RWMutex
    83  	opts        server.Options
    84  	handlers    map[string]server.Handler
    85  	subscribers map[*subscriber][]broker.Subscriber
    86  	// marks the serve as started
    87  	started bool
    88  	// used for first registration
    89  	registered bool
    90  
    91  	// registry service instance
    92  	rsvc *registry.Service
    93  }
    94  
    95  func init() {
    96  	encoding.RegisterCodec(wrapCodec{jsonCodec{}})
    97  	encoding.RegisterCodec(wrapCodec{protoCodec{}})
    98  	encoding.RegisterCodec(wrapCodec{bytesCodec{}})
    99  }
   100  
   101  func newGRPCServer(opts ...server.Option) server.Server {
   102  	options := newOptions(opts...)
   103  
   104  	// create a grpc server
   105  	srv := &grpcServer{
   106  		opts: options,
   107  		rpc: &rServer{
   108  			serviceMap: make(map[string]*service),
   109  		},
   110  		handlers:    make(map[string]server.Handler),
   111  		subscribers: make(map[*subscriber][]broker.Subscriber),
   112  		exit:        make(chan chan error),
   113  		wg:          wait(options.Context),
   114  	}
   115  
   116  	// configure the grpc server
   117  	srv.configure()
   118  
   119  	return srv
   120  }
   121  
   122  type grpcRouter struct {
   123  	h func(context.Context, server.Request, interface{}) error
   124  	m func(context.Context, server.Message) error
   125  }
   126  
   127  func (r grpcRouter) ProcessMessage(ctx context.Context, msg server.Message) error {
   128  	return r.m(ctx, msg)
   129  }
   130  
   131  func (r grpcRouter) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error {
   132  	return r.h(ctx, req, rsp)
   133  }
   134  
   135  func (g *grpcServer) configure(opts ...server.Option) {
   136  	g.Lock()
   137  	defer g.Unlock()
   138  
   139  	// Don't reprocess where there's no config
   140  	if len(opts) == 0 && g.srv != nil {
   141  		return
   142  	}
   143  
   144  	for _, o := range opts {
   145  		o(&g.opts)
   146  	}
   147  
   148  	g.wg = wait(g.opts.Context)
   149  
   150  	maxRecvMsgSize := g.maxRecvMsgSizeValue()
   151  	maxSendMsgSize := g.maxSendMsgSizeValue()
   152  
   153  	gopts := []grpc.ServerOption{
   154  		grpc.MaxRecvMsgSize(maxRecvMsgSize),
   155  		grpc.MaxSendMsgSize(maxSendMsgSize),
   156  		grpc.UnknownServiceHandler(g.handler),
   157  	}
   158  
   159  	if creds := g.getCredentials(); creds != nil {
   160  		gopts = append(gopts, grpc.Creds(creds))
   161  	}
   162  
   163  	if opts := g.getGrpcOptions(); opts != nil {
   164  		gopts = append(gopts, opts...)
   165  	}
   166  
   167  	g.rsvc = nil
   168  	g.srv = grpc.NewServer(gopts...)
   169  }
   170  
   171  func (g *grpcServer) maxRecvMsgSizeValue() int {
   172  	if g.opts.Context == nil {
   173  		return DefaultMaxRecvMsgSize
   174  	}
   175  	v := g.opts.Context.Value(maxRecvMsgSizeKey{})
   176  	if v == nil {
   177  		return DefaultMaxRecvMsgSize
   178  	}
   179  	return v.(int)
   180  }
   181  
   182  func (g *grpcServer) maxSendMsgSizeValue() int {
   183  	if g.opts.Context == nil {
   184  		return DefaultMaxSendMsgSize
   185  	}
   186  	v := g.opts.Context.Value(maxSendMsgSizeKey{})
   187  	if v == nil {
   188  		return DefaultMaxSendMsgSize
   189  	}
   190  	return v.(int)
   191  }
   192  
   193  func (g *grpcServer) getCredentials() credentials.TransportCredentials {
   194  	if g.opts.Context != nil {
   195  		if v, ok := g.opts.Context.Value(tlsAuth{}).(*tls.Config); ok && v != nil {
   196  			return credentials.NewTLS(v)
   197  		}
   198  	}
   199  	return nil
   200  }
   201  
   202  func (g *grpcServer) getGrpcOptions() []grpc.ServerOption {
   203  	if g.opts.Context == nil {
   204  		return nil
   205  	}
   206  
   207  	opts, ok := g.opts.Context.Value(grpcOptions{}).([]grpc.ServerOption)
   208  	if !ok || opts == nil {
   209  		return nil
   210  	}
   211  
   212  	return opts
   213  }
   214  
   215  func (g *grpcServer) getListener() net.Listener {
   216  	if g.opts.Context == nil {
   217  		return nil
   218  	}
   219  
   220  	if l, ok := g.opts.Context.Value(netListener{}).(net.Listener); ok && l != nil {
   221  		return l
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err error) {
   228  	defer func() {
   229  		if r := recover(); r != nil {
   230  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   231  				logger.Error("panic recovered: ", r)
   232  				logger.Error(string(debug.Stack()))
   233  			}
   234  			err = errors.InternalServerError(g.opts.Name, "panic recovered: %v", r)
   235  		} else if err != nil {
   236  			if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   237  				logger.Errorf("grpc handler got error: %s", err)
   238  			}
   239  		}
   240  	}()
   241  
   242  	if g.wg != nil {
   243  		g.wg.Add(1)
   244  		defer g.wg.Done()
   245  	}
   246  
   247  	fullMethod, ok := grpc.MethodFromServerStream(stream)
   248  	if !ok {
   249  		return status.Errorf(codes.Internal, "method does not exist in context")
   250  	}
   251  
   252  	serviceName, methodName, err := ServiceMethod(fullMethod)
   253  	if err != nil {
   254  		return status.New(codes.InvalidArgument, err.Error()).Err()
   255  	}
   256  
   257  	// get grpc metadata
   258  	gmd, ok := metadata.FromIncomingContext(stream.Context())
   259  	if !ok {
   260  		gmd = metadata.MD{}
   261  	}
   262  
   263  	// copy the metadata to go-micro.metadata
   264  	md := meta.Metadata{}
   265  	for k, v := range gmd {
   266  		md[k] = strings.Join(v, ", ")
   267  	}
   268  
   269  	// timeout for server deadline
   270  	to := md["timeout"]
   271  
   272  	// get content type
   273  	ct := defaultContentType
   274  
   275  	if ctype, ok := md["x-content-type"]; ok {
   276  		ct = ctype
   277  	}
   278  	if ctype, ok := md["content-type"]; ok {
   279  		ct = ctype
   280  	}
   281  
   282  	delete(md, "x-content-type")
   283  	delete(md, "timeout")
   284  
   285  	// create new context
   286  	ctx := meta.NewContext(stream.Context(), md)
   287  
   288  	// get peer from context
   289  	if p, ok := peer.FromContext(stream.Context()); ok {
   290  		md["Remote"] = p.Addr.String()
   291  		ctx = peer.NewContext(ctx, p)
   292  	}
   293  
   294  	// set the timeout if we have it
   295  	if len(to) > 0 {
   296  		if n, err := strconv.ParseUint(to, 10, 64); err == nil {
   297  			var cancel context.CancelFunc
   298  			ctx, cancel = context.WithTimeout(ctx, time.Duration(n))
   299  			defer cancel()
   300  		}
   301  	}
   302  
   303  	// process via router
   304  	if g.opts.Router != nil {
   305  		cc, err := g.newGRPCCodec(ct)
   306  		if err != nil {
   307  			return errors.InternalServerError(g.opts.Name, err.Error())
   308  		}
   309  		codec := &grpcCodec{
   310  			ServerStream: stream,
   311  			method:       fmt.Sprintf("%s.%s", serviceName, methodName),
   312  			endpoint:     fmt.Sprintf("%s.%s", serviceName, methodName),
   313  			target:       g.opts.Name,
   314  			c:            cc,
   315  		}
   316  
   317  		// create a client.Request
   318  		request := &rpcRequest{
   319  			service:     ServiceFromMethod(fullMethod),
   320  			contentType: ct,
   321  			method:      fmt.Sprintf("%s.%s", serviceName, methodName),
   322  			codec:       codec,
   323  			stream:      true,
   324  		}
   325  
   326  		response := &rpcResponse{
   327  			header: make(map[string]string),
   328  			codec:  codec,
   329  		}
   330  
   331  		// create a wrapped function
   332  		handler := func(ctx context.Context, req server.Request, rsp interface{}) error {
   333  			return g.opts.Router.ServeRequest(ctx, req, rsp.(server.Response))
   334  		}
   335  
   336  		// execute the wrapper for it
   337  		for i := len(g.opts.HdlrWrappers); i > 0; i-- {
   338  			handler = g.opts.HdlrWrappers[i-1](handler)
   339  		}
   340  
   341  		r := grpcRouter{h: handler}
   342  
   343  		// serve the actual request using the request router
   344  		if err := r.ServeRequest(ctx, request, response); err != nil {
   345  			if _, ok := status.FromError(err); ok {
   346  				return err
   347  			}
   348  			return status.Errorf(codes.Internal, err.Error())
   349  		}
   350  
   351  		return nil
   352  	}
   353  
   354  	// process the standard request flow
   355  	g.rpc.mu.Lock()
   356  	service := g.rpc.serviceMap[serviceName]
   357  	g.rpc.mu.Unlock()
   358  
   359  	if service == nil {
   360  		return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s", serviceName)).Err()
   361  	}
   362  
   363  	mtype := service.method[methodName]
   364  	if mtype == nil {
   365  		return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s.%s", serviceName, methodName)).Err()
   366  	}
   367  
   368  	// process unary
   369  	if !mtype.stream {
   370  		return g.processRequest(stream, service, mtype, ct, ctx)
   371  	}
   372  
   373  	// process stream
   374  	return g.processStream(stream, service, mtype, ct, ctx)
   375  }
   376  
   377  func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error {
   378  	for {
   379  		var argv, replyv reflect.Value
   380  
   381  		// Decode the argument value.
   382  		argIsValue := false // if true, need to indirect before calling.
   383  		if mtype.ArgType.Kind() == reflect.Ptr {
   384  			argv = reflect.New(mtype.ArgType.Elem())
   385  		} else {
   386  			argv = reflect.New(mtype.ArgType)
   387  			argIsValue = true
   388  		}
   389  
   390  		if cd := defaultGRPCCodecs[ct]; cd.Name() != "json" {
   391  			if err := stream.RecvMsg(argv.Interface()); err != nil {
   392  				return err
   393  			}
   394  		} else {
   395  			var raw json.RawMessage
   396  
   397  			// Unmarshal request in to a generic map[string]interface{}
   398  			if err := stream.RecvMsg(&raw); err != nil {
   399  				return err
   400  			}
   401  
   402  			// first try parsing it as normal
   403  			if err := cd.Unmarshal(raw, argv.Interface()); err != nil {
   404  				// let's try parsing it manually
   405  				var gen map[string]interface{}
   406  				if err := json.Unmarshal(raw, &gen); err != nil {
   407  					return err
   408  				}
   409  				for i := 0; i < argv.Elem().NumField(); i++ {
   410  					field := argv.Elem().Field(i)
   411  					if !field.CanSet() {
   412  						continue
   413  					}
   414  					fieldName := strings.Split(argv.Elem().Type().Field(i).Tag.Get("json"), ",")[0]
   415  					kindVal := argv.Elem().Field(i).Kind()
   416  					if len(fieldName) == 0 {
   417  						continue
   418  					}
   419  					if _, ok := gen[fieldName]; !ok {
   420  						continue
   421  					}
   422  					if s, ok := gen[fieldName].(string); ok {
   423  						// be more permissive by trying to convert string in to the correct type
   424  						switch kindVal {
   425  						case reflect.Bool:
   426  							b, err := strconv.ParseBool(s)
   427  							if err != nil {
   428  								return err
   429  							}
   430  							field.SetBool(b)
   431  						case reflect.Int64, reflect.Int32, reflect.Int:
   432  							in, err := strconv.ParseInt(s, 10, 64)
   433  							if err != nil {
   434  								return err
   435  							}
   436  							field.SetInt(in)
   437  						case reflect.Slice: // byte slice
   438  							b, err := base64.StdEncoding.DecodeString(s)
   439  							if err != nil {
   440  								return err
   441  							}
   442  							field.SetBytes(b)
   443  						default:
   444  							field.Set(reflect.ValueOf(gen[fieldName]))
   445  						}
   446  					} else {
   447  						field.Set(reflect.ValueOf(gen[fieldName]))
   448  					}
   449  				}
   450  			}
   451  		}
   452  
   453  		if argIsValue {
   454  			argv = argv.Elem()
   455  		}
   456  
   457  		// reply value
   458  		replyv = reflect.New(mtype.ReplyType.Elem())
   459  
   460  		function := mtype.method.Func
   461  		var returnValues []reflect.Value
   462  
   463  		cc, err := g.newGRPCCodec(ct)
   464  		if err != nil {
   465  			return errors.InternalServerError(g.opts.Name, err.Error())
   466  		}
   467  		b, err := cc.Marshal(argv.Interface())
   468  		if err != nil {
   469  			return err
   470  		}
   471  
   472  		// create a client.Request
   473  		r := &rpcRequest{
   474  			service:     g.opts.Name,
   475  			contentType: ct,
   476  			method:      fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
   477  			body:        b,
   478  			payload:     argv.Interface(),
   479  		}
   480  
   481  		// define the handler func
   482  		fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) {
   483  			returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)})
   484  
   485  			// The return value for the method is an error.
   486  			if rerr := returnValues[0].Interface(); rerr != nil {
   487  				err = rerr.(error)
   488  			}
   489  
   490  			return err
   491  		}
   492  
   493  		// wrap the handler func
   494  		for i := len(g.opts.HdlrWrappers); i > 0; i-- {
   495  			fn = g.opts.HdlrWrappers[i-1](fn)
   496  		}
   497  
   498  		statusCode := codes.OK
   499  		statusDesc := ""
   500  
   501  		// execute the handler
   502  		if appErr := fn(ctx, r, replyv.Interface()); appErr != nil {
   503  			var errStatus *status.Status
   504  			switch verr := appErr.(type) {
   505  			case *errors.Error:
   506  				perr := &pberr.Error{
   507  					Id:     verr.Id,
   508  					Code:   verr.Code,
   509  					Detail: verr.Detail,
   510  					Status: verr.Status,
   511  				}
   512  
   513  				// micro.Error now proto based and we can attach it to grpc status
   514  				statusCode = microError(verr)
   515  				statusDesc = verr.Error()
   516  
   517  				errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
   518  				if err != nil {
   519  					return err
   520  				}
   521  			case proto.Message:
   522  				// user defined error that proto based we can attach it to grpc status
   523  				statusCode = convertCode(appErr)
   524  				statusDesc = appErr.Error()
   525  				errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr)
   526  				if err != nil {
   527  					return err
   528  				}
   529  			default:
   530  				// default case user pass own error type that not proto based
   531  				statusCode = convertCode(verr)
   532  				statusDesc = verr.Error()
   533  				errStatus = status.New(statusCode, statusDesc)
   534  			}
   535  
   536  			return errStatus.Err()
   537  		}
   538  
   539  		if err := stream.SendMsg(replyv.Interface()); err != nil {
   540  			return err
   541  		}
   542  
   543  		return status.New(statusCode, statusDesc).Err()
   544  	}
   545  }
   546  
   547  func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error {
   548  	opts := g.opts
   549  
   550  	r := &rpcRequest{
   551  		service:     opts.Name,
   552  		contentType: ct,
   553  		method:      fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
   554  		stream:      true,
   555  	}
   556  
   557  	ss := &rpcStream{
   558  		ServerStream: stream,
   559  		request:      r,
   560  	}
   561  
   562  	function := mtype.method.Func
   563  	var returnValues []reflect.Value
   564  
   565  	// Invoke the method, providing a new value for the reply.
   566  	fn := func(ctx context.Context, req server.Request, stream interface{}) error {
   567  		returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(stream)})
   568  		if err := returnValues[0].Interface(); err != nil {
   569  			return err.(error)
   570  		}
   571  
   572  		return nil
   573  	}
   574  
   575  	for i := len(opts.HdlrWrappers); i > 0; i-- {
   576  		fn = opts.HdlrWrappers[i-1](fn)
   577  	}
   578  
   579  	statusCode := codes.OK
   580  	statusDesc := ""
   581  
   582  	if appErr := fn(ctx, r, ss); appErr != nil {
   583  		var err error
   584  		var errStatus *status.Status
   585  		switch verr := appErr.(type) {
   586  		case *errors.Error:
   587  			perr := &pberr.Error{
   588  				Id:     verr.Id,
   589  				Code:   verr.Code,
   590  				Detail: verr.Detail,
   591  				Status: verr.Status,
   592  			}
   593  			// micro.Error now proto based and we can attach it to grpc status
   594  			statusCode = microError(verr)
   595  			statusDesc = verr.Error()
   596  			errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
   597  			if err != nil {
   598  				return err
   599  			}
   600  		case proto.Message:
   601  			// user defined error that proto based we can attach it to grpc status
   602  			statusCode = convertCode(appErr)
   603  			statusDesc = appErr.Error()
   604  			errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr)
   605  			if err != nil {
   606  				return err
   607  			}
   608  		default:
   609  			// default case user pass own error type that not proto based
   610  			statusCode = convertCode(verr)
   611  			statusDesc = verr.Error()
   612  			errStatus = status.New(statusCode, statusDesc)
   613  		}
   614  
   615  		return errStatus.Err()
   616  	}
   617  
   618  	return status.New(statusCode, statusDesc).Err()
   619  }
   620  
   621  func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) {
   622  	codecs := make(map[string]encoding.Codec)
   623  	if g.opts.Context != nil {
   624  		if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil {
   625  			codecs = v
   626  		}
   627  	}
   628  	if c, ok := codecs[contentType]; ok {
   629  		return c, nil
   630  	}
   631  	if c, ok := defaultGRPCCodecs[contentType]; ok {
   632  		return c, nil
   633  	}
   634  	return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
   635  }
   636  
   637  func (g *grpcServer) Options() server.Options {
   638  	g.RLock()
   639  	opts := g.opts
   640  	g.RUnlock()
   641  
   642  	return opts
   643  }
   644  
   645  func (g *grpcServer) Init(opts ...server.Option) error {
   646  	g.configure(opts...)
   647  	return nil
   648  }
   649  
   650  func (g *grpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler {
   651  	return newRpcHandler(h, opts...)
   652  }
   653  
   654  func (g *grpcServer) Handle(h server.Handler) error {
   655  	if err := g.rpc.register(h.Handler()); err != nil {
   656  		return err
   657  	}
   658  
   659  	g.handlers[h.Name()] = h
   660  	return nil
   661  }
   662  
   663  func (g *grpcServer) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber {
   664  	return newSubscriber(topic, sb, opts...)
   665  }
   666  
   667  func (g *grpcServer) Subscribe(sb server.Subscriber) error {
   668  	sub, ok := sb.(*subscriber)
   669  	if !ok {
   670  		return fmt.Errorf("invalid subscriber: expected *subscriber")
   671  	}
   672  	if len(sub.handlers) == 0 {
   673  		return fmt.Errorf("invalid subscriber: no handler functions")
   674  	}
   675  
   676  	if err := validateSubscriber(sb); err != nil {
   677  		return err
   678  	}
   679  
   680  	g.Lock()
   681  	if _, ok = g.subscribers[sub]; ok {
   682  		g.Unlock()
   683  		return fmt.Errorf("subscriber %v already exists", sub)
   684  	}
   685  
   686  	g.subscribers[sub] = nil
   687  	g.Unlock()
   688  	return nil
   689  }
   690  
   691  func (g *grpcServer) Register() error {
   692  	g.RLock()
   693  	rsvc := g.rsvc
   694  	config := g.opts
   695  	g.RUnlock()
   696  
   697  	// only register if it exists or is not noop
   698  	if config.Registry == nil || config.Registry.String() == "noop" {
   699  		return nil
   700  	}
   701  
   702  	regFunc := func(service *registry.Service) error {
   703  		var regErr error
   704  
   705  		for i := 0; i < 3; i++ {
   706  			// set the ttl and namespace
   707  			rOpts := []registry.RegisterOption{
   708  				registry.RegisterTTL(config.RegisterTTL),
   709  				registry.RegisterDomain(g.opts.Namespace),
   710  			}
   711  
   712  			// attempt to register
   713  			if err := config.Registry.Register(service, rOpts...); err != nil {
   714  				// set the error
   715  				regErr = err
   716  				// backoff then retry
   717  				time.Sleep(backoff.Do(i + 1))
   718  				continue
   719  			}
   720  			// success so nil error
   721  			regErr = nil
   722  			break
   723  		}
   724  
   725  		return regErr
   726  	}
   727  
   728  	// if service already filled, reuse it and return early
   729  	if rsvc != nil {
   730  		if err := regFunc(rsvc); err != nil {
   731  			return err
   732  		}
   733  		return nil
   734  	}
   735  
   736  	var err error
   737  	var advt, host, port string
   738  	var cacheService bool
   739  
   740  	// check the advertise address first
   741  	// if it exists then use it, otherwise
   742  	// use the address
   743  	if len(config.Advertise) > 0 {
   744  		advt = config.Advertise
   745  	} else {
   746  		advt = config.Address
   747  	}
   748  
   749  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   750  		// ipv6 address in format [host]:port or ipv4 host:port
   751  		host, port, err = net.SplitHostPort(advt)
   752  		if err != nil {
   753  			return err
   754  		}
   755  	} else {
   756  		host = advt
   757  	}
   758  
   759  	if ip := net.ParseIP(host); ip != nil {
   760  		cacheService = true
   761  	}
   762  
   763  	addr, err := addr.Extract(host)
   764  	if err != nil {
   765  		return err
   766  	}
   767  
   768  	// make copy of metadata
   769  	md := meta.Copy(config.Metadata)
   770  
   771  	// register service
   772  	node := &registry.Node{
   773  		Id:       config.Name + "-" + config.Id,
   774  		Address:  mnet.HostPort(addr, port),
   775  		Metadata: md,
   776  	}
   777  
   778  	node.Metadata["broker"] = config.Broker.String()
   779  	node.Metadata["registry"] = config.Registry.String()
   780  	node.Metadata["server"] = g.String()
   781  	node.Metadata["transport"] = g.String()
   782  	node.Metadata["protocol"] = "grpc"
   783  
   784  	g.RLock()
   785  	// Maps are ordered randomly, sort the keys for consistency
   786  	var handlerList []string
   787  	for n, e := range g.handlers {
   788  		// Only advertise non internal handlers
   789  		if !e.Options().Internal {
   790  			handlerList = append(handlerList, n)
   791  		}
   792  	}
   793  	sort.Strings(handlerList)
   794  
   795  	var subscriberList []*subscriber
   796  	for e := range g.subscribers {
   797  		// Only advertise non internal subscribers
   798  		if !e.Options().Internal {
   799  			subscriberList = append(subscriberList, e)
   800  		}
   801  	}
   802  	sort.Slice(subscriberList, func(i, j int) bool {
   803  		return subscriberList[i].topic > subscriberList[j].topic
   804  	})
   805  
   806  	endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList))
   807  	for _, n := range handlerList {
   808  		endpoints = append(endpoints, g.handlers[n].Endpoints()...)
   809  	}
   810  	for _, e := range subscriberList {
   811  		endpoints = append(endpoints, e.Endpoints()...)
   812  	}
   813  	g.RUnlock()
   814  
   815  	service := &registry.Service{
   816  		Name:      config.Name,
   817  		Version:   config.Version,
   818  		Nodes:     []*registry.Node{node},
   819  		Endpoints: endpoints,
   820  	}
   821  
   822  	g.RLock()
   823  	registered := g.registered
   824  	g.RUnlock()
   825  
   826  	if !registered {
   827  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   828  			logger.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
   829  		}
   830  	}
   831  
   832  	// register the service
   833  	if err := regFunc(service); err != nil {
   834  		return err
   835  	}
   836  
   837  	// already registered? don't need to register subscribers
   838  	if registered {
   839  		return nil
   840  	}
   841  
   842  	g.Lock()
   843  	defer g.Unlock()
   844  
   845  	for sb := range g.subscribers {
   846  		handler := g.createSubHandler(sb, g.opts)
   847  		var opts []broker.SubscribeOption
   848  		if queue := sb.Options().Queue; len(queue) > 0 {
   849  			opts = append(opts, broker.Queue(queue))
   850  		}
   851  
   852  		if cx := sb.Options().Context; cx != nil {
   853  			opts = append(opts, broker.SubscribeContext(cx))
   854  		}
   855  
   856  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   857  			logger.Infof("Subscribing to topic: %s", sb.Topic())
   858  		}
   859  		sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...)
   860  		if err != nil {
   861  			return err
   862  		}
   863  		g.subscribers[sb] = []broker.Subscriber{sub}
   864  	}
   865  
   866  	g.registered = true
   867  	if cacheService {
   868  		g.rsvc = service
   869  	}
   870  
   871  	return nil
   872  }
   873  
   874  func (g *grpcServer) Deregister() error {
   875  	var err error
   876  	var advt, host, port string
   877  
   878  	g.RLock()
   879  	config := g.opts
   880  	g.RUnlock()
   881  
   882  	// only register if it exists or is not noop
   883  	if config.Registry == nil || config.Registry.String() == "noop" {
   884  		return nil
   885  	}
   886  
   887  	// check the advertise address first
   888  	// if it exists then use it, otherwise
   889  	// use the address
   890  	if len(config.Advertise) > 0 {
   891  		advt = config.Advertise
   892  	} else {
   893  		advt = config.Address
   894  	}
   895  
   896  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   897  		// ipv6 address in format [host]:port or ipv4 host:port
   898  		host, port, err = net.SplitHostPort(advt)
   899  		if err != nil {
   900  			return err
   901  		}
   902  	} else {
   903  		host = advt
   904  	}
   905  
   906  	addr, err := addr.Extract(host)
   907  	if err != nil {
   908  		return err
   909  	}
   910  
   911  	node := &registry.Node{
   912  		Id:      config.Name + "-" + config.Id,
   913  		Address: mnet.HostPort(addr, port),
   914  	}
   915  
   916  	service := &registry.Service{
   917  		Name:    config.Name,
   918  		Version: config.Version,
   919  		Nodes:   []*registry.Node{node},
   920  	}
   921  
   922  	if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   923  		logger.Infof("Deregistering node: %s", node.Id)
   924  	}
   925  
   926  	opt := registry.DeregisterDomain(g.opts.Namespace)
   927  	if err := config.Registry.Deregister(service, opt); err != nil {
   928  		return err
   929  	}
   930  
   931  	g.Lock()
   932  	g.rsvc = nil
   933  
   934  	if !g.registered {
   935  		g.Unlock()
   936  		return nil
   937  	}
   938  
   939  	g.registered = false
   940  
   941  	wg := sync.WaitGroup{}
   942  	for sb, subs := range g.subscribers {
   943  		for _, sub := range subs {
   944  			wg.Add(1)
   945  			go func(s broker.Subscriber) {
   946  				defer wg.Done()
   947  				if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   948  					logger.Infof("Unsubscribing from topic: %s", s.Topic())
   949  				}
   950  				s.Unsubscribe()
   951  			}(sub)
   952  		}
   953  		g.subscribers[sb] = nil
   954  	}
   955  	wg.Wait()
   956  
   957  	g.Unlock()
   958  	return nil
   959  }
   960  
   961  func (g *grpcServer) Start() error {
   962  	g.RLock()
   963  	if g.started {
   964  		g.RUnlock()
   965  		return nil
   966  	}
   967  	g.RUnlock()
   968  
   969  	config := g.Options()
   970  
   971  	// micro: config.Transport.Listen(config.Address)
   972  	var ts net.Listener
   973  
   974  	if l := g.getListener(); l != nil {
   975  		ts = l
   976  	} else {
   977  		var err error
   978  
   979  		// check the tls config for secure connect
   980  		if tc := config.TLSConfig; tc != nil {
   981  			ts, err = tls.Listen("tcp", config.Address, tc)
   982  			// otherwise just plain tcp listener
   983  		} else {
   984  			ts, err = net.Listen("tcp", config.Address)
   985  		}
   986  		if err != nil {
   987  			return err
   988  		}
   989  	}
   990  
   991  	if g.opts.Context != nil {
   992  		if c, ok := g.opts.Context.Value(maxConnKey{}).(int); ok && c > 0 {
   993  			ts = netutil.LimitListener(ts, c)
   994  		}
   995  	}
   996  
   997  	if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   998  		logger.Infof("Server [grpc] Listening on %s", ts.Addr().String())
   999  	}
  1000  	g.Lock()
  1001  	g.opts.Address = ts.Addr().String()
  1002  	g.Unlock()
  1003  
  1004  	// only connect if we're subscribed
  1005  	if len(g.subscribers) > 0 {
  1006  		// connect to the broker
  1007  		if err := config.Broker.Connect(); err != nil {
  1008  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1009  				logger.Errorf("Broker [%s] connect error: %v", config.Broker.String(), err)
  1010  			}
  1011  			return err
  1012  		}
  1013  
  1014  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
  1015  			logger.Infof("Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address())
  1016  		}
  1017  	}
  1018  
  1019  	// announce self to the world
  1020  	if err := g.Register(); err != nil {
  1021  		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1022  			logger.Errorf("Server register error: %v", err)
  1023  		}
  1024  	}
  1025  
  1026  	if g.opts.Context != nil {
  1027  		gRPCWebAddr := ":8082"
  1028  		if g.opts.Context.Value(grpcWebPort{}) != nil {
  1029  			if p, ok := g.opts.Context.Value(grpcWebPort{}).(string); ok && p != "" {
  1030  				gRPCWebAddr = p
  1031  			}
  1032  		}
  1033  
  1034  		if c, ok := g.opts.Context.Value(grpcWebOptions{}).([]grpcweb.Option); ok && len(c) > 0 {
  1035  			wrappedGrpc := grpcweb.WrapServer(g.srv, c...)
  1036  			webGRPCServer := &http.Server{
  1037  				Addr:      gRPCWebAddr,
  1038  				TLSConfig: config.TLSConfig,
  1039  				Handler:   http.Handler(wrappedGrpc),
  1040  			}
  1041  
  1042  			go webGRPCServer.ListenAndServe()
  1043  
  1044  			logger.Infof("Server [gRPC-Web] Listening on %s", gRPCWebAddr)
  1045  		}
  1046  	}
  1047  
  1048  	// micro: go ts.Accept(s.accept)
  1049  	go func() {
  1050  		if err := g.srv.Serve(ts); err != nil {
  1051  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1052  				logger.Errorf("gRPC Server start error: %v", err)
  1053  			}
  1054  		}
  1055  	}()
  1056  
  1057  	go func() {
  1058  		t := new(time.Ticker)
  1059  
  1060  		// only process if it exists
  1061  		if g.opts.RegisterInterval > time.Duration(0) {
  1062  			// new ticker
  1063  			t = time.NewTicker(g.opts.RegisterInterval)
  1064  		}
  1065  
  1066  		// return error chan
  1067  		var ch chan error
  1068  
  1069  	Loop:
  1070  		for {
  1071  			select {
  1072  			// register self on interval
  1073  			case <-t.C:
  1074  				if err := g.Register(); err != nil {
  1075  					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1076  						logger.Error("Server register error: ", err)
  1077  					}
  1078  				}
  1079  			// wait for exit
  1080  			case ch = <-g.exit:
  1081  				break Loop
  1082  			}
  1083  		}
  1084  
  1085  		// deregister self
  1086  		if err := g.Deregister(); err != nil {
  1087  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1088  				logger.Error("Server deregister error: ", err)
  1089  			}
  1090  		}
  1091  
  1092  		// wait for waitgroup
  1093  		if g.wg != nil {
  1094  			g.wg.Wait()
  1095  		}
  1096  
  1097  		// stop the grpc server
  1098  		exit := make(chan bool)
  1099  
  1100  		go func() {
  1101  			g.srv.GracefulStop()
  1102  			close(exit)
  1103  		}()
  1104  
  1105  		select {
  1106  		case <-exit:
  1107  		case <-time.After(time.Second):
  1108  			g.srv.Stop()
  1109  		}
  1110  
  1111  		// close transport
  1112  		ch <- nil
  1113  
  1114  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
  1115  			logger.Infof("Broker [%s] Disconnected from %s", config.Broker.String(), config.Broker.Address())
  1116  		}
  1117  		// disconnect broker
  1118  		if err := config.Broker.Disconnect(); err != nil {
  1119  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
  1120  				logger.Errorf("Broker [%s] disconnect error: %v", config.Broker.String(), err)
  1121  			}
  1122  		}
  1123  	}()
  1124  
  1125  	// mark the server as started
  1126  	g.Lock()
  1127  	g.started = true
  1128  	g.Unlock()
  1129  
  1130  	return nil
  1131  }
  1132  
  1133  func hasHTTP2Preface(r io.Reader) bool {
  1134  	var b [len(http2.ClientPreface)]byte
  1135  	last := 0
  1136  
  1137  	for {
  1138  		n, err := r.Read(b[last:])
  1139  		if err != nil {
  1140  			return false
  1141  		}
  1142  
  1143  		last += n
  1144  		eq := string(b[:last]) == http2.ClientPreface[:last]
  1145  		if last == len(http2.ClientPreface) {
  1146  			return eq
  1147  		}
  1148  		if !eq {
  1149  			return false
  1150  		}
  1151  	}
  1152  }
  1153  
  1154  func (g *grpcServer) Stop() error {
  1155  	g.RLock()
  1156  	if !g.started {
  1157  		g.RUnlock()
  1158  		return nil
  1159  	}
  1160  	g.RUnlock()
  1161  
  1162  	ch := make(chan error)
  1163  	g.exit <- ch
  1164  
  1165  	var err error
  1166  	select {
  1167  	case err = <-ch:
  1168  		g.Lock()
  1169  		g.rsvc = nil
  1170  		g.started = false
  1171  		g.Unlock()
  1172  	}
  1173  
  1174  	return err
  1175  }
  1176  
  1177  func (g *grpcServer) String() string {
  1178  	return "grpc"
  1179  }
  1180  
  1181  func NewServer(opts ...server.Option) server.Server {
  1182  	return newGRPCServer(opts...)
  1183  }