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, µTransport{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 }