1/* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19package grpc 20 21import ( 22 "encoding/json" 23 "time" 24 25 "google.golang.org/grpc/grpclog" 26) 27 28const maxInt = int(^uint(0) >> 1) 29 30// MethodConfig defines the configuration recommended by the service providers for a 31// particular method. 32// DEPRECATED: Users should not use this struct. Service config should be received 33// through name resolver, as specified here 34// https://github.com/grpc/grpc/blob/master/doc/service_config.md 35type MethodConfig struct { 36 // WaitForReady indicates whether RPCs sent to this method should wait until 37 // the connection is ready by default (!failfast). The value specified via the 38 // gRPC client API will override the value set here. 39 WaitForReady *bool 40 // Timeout is the default timeout for RPCs sent to this method. The actual 41 // deadline used will be the minimum of the value specified here and the value 42 // set by the application via the gRPC client API. If either one is not set, 43 // then the other will be used. If neither is set, then the RPC has no deadline. 44 Timeout *time.Duration 45 // MaxReqSize is the maximum allowed payload size for an individual request in a 46 // stream (client->server) in bytes. The size which is measured is the serialized 47 // payload after per-message compression (but before stream compression) in bytes. 48 // The actual value used is the minimum of the value specified here and the value set 49 // by the application via the gRPC client API. If either one is not set, then the other 50 // will be used. If neither is set, then the built-in default is used. 51 MaxReqSize *int 52 // MaxRespSize is the maximum allowed payload size for an individual response in a 53 // stream (server->client) in bytes. 54 MaxRespSize *int 55} 56 57// ServiceConfig is provided by the service provider and contains parameters for how 58// clients that connect to the service should behave. 59// DEPRECATED: Users should not use this struct. Service config should be received 60// through name resolver, as specified here 61// https://github.com/grpc/grpc/blob/master/doc/service_config.md 62type ServiceConfig struct { 63 // LB is the load balancer the service providers recommends. The balancer specified 64 // via grpc.WithBalancer will override this. 65 LB *string 66 // Methods contains a map for the methods in this service. 67 // If there is an exact match for a method (i.e. /service/method) in the map, use the corresponding MethodConfig. 68 // If there's no exact match, look for the default config for the service (/service/) and use the corresponding MethodConfig if it exists. 69 // Otherwise, the method has no MethodConfig to use. 70 Methods map[string]MethodConfig 71} 72 73func parseTimeout(t *string) (*time.Duration, error) { 74 if t == nil { 75 return nil, nil 76 } 77 d, err := time.ParseDuration(*t) 78 return &d, err 79} 80 81type jsonName struct { 82 Service *string 83 Method *string 84} 85 86func (j jsonName) generatePath() (string, bool) { 87 if j.Service == nil { 88 return "", false 89 } 90 res := "/" + *j.Service + "/" 91 if j.Method != nil { 92 res += *j.Method 93 } 94 return res, true 95} 96 97// TODO(lyuxuan): delete this struct after cleaning up old service config implementation. 98type jsonMC struct { 99 Name *[]jsonName 100 WaitForReady *bool 101 Timeout *string 102 MaxRequestMessageBytes *int64 103 MaxResponseMessageBytes *int64 104} 105 106// TODO(lyuxuan): delete this struct after cleaning up old service config implementation. 107type jsonSC struct { 108 LoadBalancingPolicy *string 109 MethodConfig *[]jsonMC 110} 111 112func parseServiceConfig(js string) (ServiceConfig, error) { 113 var rsc jsonSC 114 err := json.Unmarshal([]byte(js), &rsc) 115 if err != nil { 116 grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) 117 return ServiceConfig{}, err 118 } 119 sc := ServiceConfig{ 120 LB: rsc.LoadBalancingPolicy, 121 Methods: make(map[string]MethodConfig), 122 } 123 if rsc.MethodConfig == nil { 124 return sc, nil 125 } 126 127 for _, m := range *rsc.MethodConfig { 128 if m.Name == nil { 129 continue 130 } 131 d, err := parseTimeout(m.Timeout) 132 if err != nil { 133 grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) 134 return ServiceConfig{}, err 135 } 136 137 mc := MethodConfig{ 138 WaitForReady: m.WaitForReady, 139 Timeout: d, 140 } 141 if m.MaxRequestMessageBytes != nil { 142 if *m.MaxRequestMessageBytes > int64(maxInt) { 143 mc.MaxReqSize = newInt(maxInt) 144 } else { 145 mc.MaxReqSize = newInt(int(*m.MaxRequestMessageBytes)) 146 } 147 } 148 if m.MaxResponseMessageBytes != nil { 149 if *m.MaxResponseMessageBytes > int64(maxInt) { 150 mc.MaxRespSize = newInt(maxInt) 151 } else { 152 mc.MaxRespSize = newInt(int(*m.MaxResponseMessageBytes)) 153 } 154 } 155 for _, n := range *m.Name { 156 if path, valid := n.generatePath(); valid { 157 sc.Methods[path] = mc 158 } 159 } 160 } 161 162 return sc, nil 163} 164 165func min(a, b *int) *int { 166 if *a < *b { 167 return a 168 } 169 return b 170} 171 172func getMaxSize(mcMax, doptMax *int, defaultVal int) *int { 173 if mcMax == nil && doptMax == nil { 174 return &defaultVal 175 } 176 if mcMax != nil && doptMax != nil { 177 return min(mcMax, doptMax) 178 } 179 if mcMax != nil { 180 return mcMax 181 } 182 return doptMax 183} 184 185func newBool(b bool) *bool { 186 return &b 187} 188 189func newInt(b int) *int { 190 return &b 191} 192 193func newDuration(b time.Duration) *time.Duration { 194 return &b 195} 196 197func newString(b string) *string { 198 return &b 199} 200