gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/transport/grpc/grpc.go (about)

     1  // Package grpc provides a grpc transport
     2  package grpc
     3  
     4  import (
     5  	"context"
     6  	"crypto/tls"
     7  	"net"
     8  
     9  	"gitee.com/liuxuezhan/go-micro-v1.18.0/transport"
    10  	maddr "gitee.com/liuxuezhan/go-micro-v1.18.0/util/addr"
    11  	mnet "gitee.com/liuxuezhan/go-micro-v1.18.0/util/net"
    12  	mls "gitee.com/liuxuezhan/go-micro-v1.18.0/util/tls"
    13  
    14  	"google.golang.org/grpc"
    15  	"google.golang.org/grpc/credentials"
    16  
    17  	pb "gitee.com/liuxuezhan/go-micro-v1.18.0/transport/grpc/proto"
    18  )
    19  
    20  type grpcTransport struct {
    21  	opts transport.Options
    22  }
    23  
    24  type grpcTransportListener struct {
    25  	listener net.Listener
    26  	secure   bool
    27  	tls      *tls.Config
    28  }
    29  
    30  func getTLSConfig(addr string) (*tls.Config, error) {
    31  	hosts := []string{addr}
    32  
    33  	// check if its a valid host:port
    34  	if host, _, err := net.SplitHostPort(addr); err == nil {
    35  		if len(host) == 0 {
    36  			hosts = maddr.IPs()
    37  		} else {
    38  			hosts = []string{host}
    39  		}
    40  	}
    41  
    42  	// generate a certificate
    43  	cert, err := mls.Certificate(hosts...)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
    49  }
    50  
    51  func (t *grpcTransportListener) Addr() string {
    52  	return t.listener.Addr().String()
    53  }
    54  
    55  func (t *grpcTransportListener) Close() error {
    56  	return t.listener.Close()
    57  }
    58  
    59  func (t *grpcTransportListener) Accept(fn func(transport.Socket)) error {
    60  	var opts []grpc.ServerOption
    61  
    62  	// setup tls if specified
    63  	if t.secure || t.tls != nil {
    64  		config := t.tls
    65  		if config == nil {
    66  			var err error
    67  			addr := t.listener.Addr().String()
    68  			config, err = getTLSConfig(addr)
    69  			if err != nil {
    70  				return err
    71  			}
    72  		}
    73  
    74  		creds := credentials.NewTLS(config)
    75  		opts = append(opts, grpc.Creds(creds))
    76  	}
    77  
    78  	// new service
    79  	srv := grpc.NewServer(opts...)
    80  
    81  	// register service
    82  	pb.RegisterTransportServer(srv, &microTransport{addr: t.listener.Addr().String(), fn: fn})
    83  
    84  	// start serving
    85  	return srv.Serve(t.listener)
    86  }
    87  
    88  func (t *grpcTransport) Dial(addr string, opts ...transport.DialOption) (transport.Client, error) {
    89  	dopts := transport.DialOptions{
    90  		Timeout: transport.DefaultDialTimeout,
    91  	}
    92  
    93  	for _, opt := range opts {
    94  		opt(&dopts)
    95  	}
    96  
    97  	options := []grpc.DialOption{
    98  		grpc.WithTimeout(dopts.Timeout),
    99  	}
   100  
   101  	if t.opts.Secure || t.opts.TLSConfig != nil {
   102  		config := t.opts.TLSConfig
   103  		if config == nil {
   104  			config = &tls.Config{
   105  				InsecureSkipVerify: true,
   106  			}
   107  		}
   108  		creds := credentials.NewTLS(config)
   109  		options = append(options, grpc.WithTransportCredentials(creds))
   110  	} else {
   111  		options = append(options, grpc.WithInsecure())
   112  	}
   113  
   114  	// dial the server
   115  	conn, err := grpc.Dial(addr, options...)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	// create stream
   121  	stream, err := pb.NewTransportClient(conn).Stream(context.Background())
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	// return a client
   127  	return &grpcTransportClient{
   128  		conn:   conn,
   129  		stream: stream,
   130  		local:  "localhost",
   131  		remote: addr,
   132  	}, nil
   133  }
   134  
   135  func (t *grpcTransport) Listen(addr string, opts ...transport.ListenOption) (transport.Listener, error) {
   136  	var options transport.ListenOptions
   137  	for _, o := range opts {
   138  		o(&options)
   139  	}
   140  
   141  	ln, err := mnet.Listen(addr, func(addr string) (net.Listener, error) {
   142  		return net.Listen("tcp", addr)
   143  	})
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	return &grpcTransportListener{
   149  		listener: ln,
   150  		tls:      t.opts.TLSConfig,
   151  		secure:   t.opts.Secure,
   152  	}, nil
   153  }
   154  
   155  func (t *grpcTransport) Init(opts ...transport.Option) error {
   156  	for _, o := range opts {
   157  		o(&t.opts)
   158  	}
   159  	return nil
   160  }
   161  
   162  func (t *grpcTransport) Options() transport.Options {
   163  	return t.opts
   164  }
   165  
   166  func (t *grpcTransport) String() string {
   167  	return "grpc"
   168  }
   169  
   170  func NewTransport(opts ...transport.Option) transport.Transport {
   171  	var options transport.Options
   172  	for _, o := range opts {
   173  		o(&options)
   174  	}
   175  	return &grpcTransport{opts: options}
   176  }