github.com/annwntech/go-micro/v2@v2.9.5/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 "github.com/annwntech/go-micro/v2/transport" 10 maddr "github.com/annwntech/go-micro/v2/util/addr" 11 mnet "github.com/annwntech/go-micro/v2/util/net" 12 mls "github.com/annwntech/go-micro/v2/util/tls" 13 14 "google.golang.org/grpc" 15 "google.golang.org/grpc/credentials" 16 17 pb "github.com/annwntech/go-micro/v2/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, µTransport{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 }