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

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/network/transport/grpc/grpc.go
    14  
    15  // Package grpc provides a grpc transport
    16  package grpc
    17  
    18  import (
    19  	"context"
    20  	"crypto/tls"
    21  	"net"
    22  
    23  	pb "github.com/tickoalcantara12/micro/v3/proto/transport"
    24  	"github.com/tickoalcantara12/micro/v3/service/network/transport"
    25  	maddr "github.com/tickoalcantara12/micro/v3/util/addr"
    26  	mnet "github.com/tickoalcantara12/micro/v3/util/net"
    27  	mls "github.com/tickoalcantara12/micro/v3/util/tls"
    28  
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/credentials"
    31  )
    32  
    33  type grpcTransport struct {
    34  	opts transport.Options
    35  }
    36  
    37  type grpcTransportListener struct {
    38  	listener net.Listener
    39  	secure   bool
    40  	tls      *tls.Config
    41  }
    42  
    43  func getTLSConfig(addr string) (*tls.Config, error) {
    44  	hosts := []string{addr}
    45  
    46  	// check if its a valid host:port
    47  	if host, _, err := net.SplitHostPort(addr); err == nil {
    48  		if len(host) == 0 {
    49  			hosts = maddr.IPs()
    50  		} else {
    51  			hosts = []string{host}
    52  		}
    53  	}
    54  
    55  	// generate a certificate
    56  	cert, err := mls.Certificate(hosts...)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
    62  }
    63  
    64  func (t *grpcTransportListener) Addr() string {
    65  	return t.listener.Addr().String()
    66  }
    67  
    68  func (t *grpcTransportListener) Close() error {
    69  	return t.listener.Close()
    70  }
    71  
    72  func (t *grpcTransportListener) Accept(fn func(transport.Socket)) error {
    73  	var opts []grpc.ServerOption
    74  
    75  	// setup tls if specified
    76  	if t.secure || t.tls != nil {
    77  		config := t.tls
    78  		if config == nil {
    79  			var err error
    80  			addr := t.listener.Addr().String()
    81  			config, err = getTLSConfig(addr)
    82  			if err != nil {
    83  				return err
    84  			}
    85  		}
    86  
    87  		creds := credentials.NewTLS(config)
    88  		opts = append(opts, grpc.Creds(creds))
    89  	}
    90  
    91  	// new service
    92  	srv := grpc.NewServer(opts...)
    93  
    94  	// register service
    95  	pb.RegisterTransportServer(srv, &microTransport{addr: t.listener.Addr().String(), fn: fn})
    96  
    97  	// start serving
    98  	return srv.Serve(t.listener)
    99  }
   100  
   101  func (t *grpcTransport) Dial(addr string, opts ...transport.DialOption) (transport.Client, error) {
   102  	dopts := transport.DialOptions{
   103  		Timeout: transport.DefaultDialTimeout,
   104  	}
   105  
   106  	for _, opt := range opts {
   107  		opt(&dopts)
   108  	}
   109  
   110  	options := []grpc.DialOption{}
   111  
   112  	if t.opts.Secure || t.opts.TLSConfig != nil {
   113  		config := t.opts.TLSConfig
   114  		if config == nil {
   115  			config = &tls.Config{
   116  				InsecureSkipVerify: true,
   117  			}
   118  		}
   119  		creds := credentials.NewTLS(config)
   120  		options = append(options, grpc.WithTransportCredentials(creds))
   121  	} else {
   122  		options = append(options, grpc.WithInsecure())
   123  	}
   124  
   125  	// dial the server
   126  	ctx, cancel := context.WithTimeout(context.Background(), dopts.Timeout)
   127  	defer cancel()
   128  	conn, err := grpc.DialContext(ctx, addr, options...)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  
   133  	// create stream
   134  	stream, err := pb.NewTransportClient(conn).Stream(context.Background())
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	// return a client
   140  	return &grpcTransportClient{
   141  		conn:   conn,
   142  		stream: stream,
   143  		local:  "localhost",
   144  		remote: addr,
   145  	}, nil
   146  }
   147  
   148  func (t *grpcTransport) Listen(addr string, opts ...transport.ListenOption) (transport.Listener, error) {
   149  	var options transport.ListenOptions
   150  	for _, o := range opts {
   151  		o(&options)
   152  	}
   153  
   154  	ln, err := mnet.Listen(addr, func(addr string) (net.Listener, error) {
   155  		return net.Listen("tcp", addr)
   156  	})
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  
   161  	return &grpcTransportListener{
   162  		listener: ln,
   163  		tls:      t.opts.TLSConfig,
   164  		secure:   t.opts.Secure,
   165  	}, nil
   166  }
   167  
   168  func (t *grpcTransport) Init(opts ...transport.Option) error {
   169  	for _, o := range opts {
   170  		o(&t.opts)
   171  	}
   172  	return nil
   173  }
   174  
   175  func (t *grpcTransport) Options() transport.Options {
   176  	return t.opts
   177  }
   178  
   179  func (t *grpcTransport) String() string {
   180  	return "grpc"
   181  }
   182  
   183  func NewTransport(opts ...transport.Option) transport.Transport {
   184  	var options transport.Options
   185  	for _, o := range opts {
   186  		o(&options)
   187  	}
   188  	return &grpcTransport{opts: options}
   189  }