dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/dubbo/impl/hessian.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. 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 package impl 19 20 import ( 21 "math" 22 "reflect" 23 "strconv" 24 "strings" 25 "time" 26 ) 27 28 import ( 29 hessian "github.com/apache/dubbo-go-hessian2" 30 "github.com/apache/dubbo-go-hessian2/java_exception" 31 32 "github.com/dubbogo/gost/log/logger" 33 34 perrors "github.com/pkg/errors" 35 ) 36 37 import ( 38 "dubbo.apache.org/dubbo-go/v3/common" 39 "dubbo.apache.org/dubbo-go/v3/common/constant" 40 ) 41 42 type HessianSerializer struct{} 43 44 func (h HessianSerializer) Marshal(p DubboPackage) ([]byte, error) { 45 encoder := hessian.NewEncoder() 46 if p.IsRequest() { 47 return marshalRequest(encoder, p) 48 } 49 return marshalResponse(encoder, p) 50 } 51 52 func (h HessianSerializer) Unmarshal(input []byte, p *DubboPackage) error { 53 if p.IsHeartBeat() { 54 return nil 55 } 56 if p.IsRequest() { 57 return unmarshalRequestBody(input, p) 58 } 59 return unmarshalResponseBody(input, p) 60 } 61 62 func marshalResponse(encoder *hessian.Encoder, p DubboPackage) ([]byte, error) { 63 header := p.Header 64 response := EnsureResponsePayload(p.Body) 65 if header.ResponseStatus == Response_OK { 66 if p.IsHeartBeat() { 67 _ = encoder.Encode(nil) 68 } else { 69 var version string 70 if attachmentVersion, ok := response.Attachments[DUBBO_VERSION_KEY]; ok { 71 version = attachmentVersion.(string) 72 } 73 atta := isSupportResponseAttachment(version) 74 75 var resWithException, resValue, resNullValue int32 76 if atta { 77 resWithException = RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS 78 resValue = RESPONSE_VALUE_WITH_ATTACHMENTS 79 resNullValue = RESPONSE_NULL_VALUE_WITH_ATTACHMENTS 80 } else { 81 resWithException = RESPONSE_WITH_EXCEPTION 82 resValue = RESPONSE_VALUE 83 resNullValue = RESPONSE_NULL_VALUE 84 } 85 86 if response.Exception != nil { // throw error 87 _ = encoder.Encode(resWithException) 88 if t, ok := response.Exception.(java_exception.Throwabler); ok { 89 _ = encoder.Encode(t) 90 } else { 91 _ = encoder.Encode(java_exception.NewThrowable(response.Exception.Error())) 92 } 93 } else { 94 if response.RspObj == nil { 95 _ = encoder.Encode(resNullValue) 96 } else { 97 _ = encoder.Encode(resValue) 98 _ = encoder.Encode(response.RspObj) // result 99 } 100 } 101 102 if atta { 103 _ = encoder.Encode(response.Attachments) // attachments 104 } 105 } 106 } else { 107 if response.Exception != nil { // throw error 108 _ = encoder.Encode(response.Exception.Error()) 109 } else { 110 _ = encoder.Encode(response.RspObj) 111 } 112 } 113 bs := encoder.Buffer() 114 // encNull 115 bs = append(bs, byte('N')) 116 return bs, nil 117 } 118 119 func marshalRequest(encoder *hessian.Encoder, p DubboPackage) ([]byte, error) { 120 service := p.Service 121 request := EnsureRequestPayload(p.Body) 122 _ = encoder.Encode(DEFAULT_DUBBO_PROTOCOL_VERSION) 123 _ = encoder.Encode(service.Path) 124 _ = encoder.Encode(service.Version) 125 _ = encoder.Encode(service.Method) 126 127 args, ok := request.Params.([]interface{}) 128 129 if !ok { 130 logger.Infof("request args are: %+v", request.Params) 131 return nil, perrors.Errorf("@params is not of type: []interface{}") 132 } 133 types, err := GetArgsTypeList(args) 134 if err != nil { 135 return nil, perrors.Wrapf(err, " PackRequest(args:%+v)", args) 136 } 137 _ = encoder.Encode(types) 138 for _, v := range args { 139 _ = encoder.Encode(v) 140 } 141 142 request.Attachments[PATH_KEY] = service.Path 143 request.Attachments[VERSION_KEY] = service.Version 144 if len(service.Group) > 0 { 145 request.Attachments[GROUP_KEY] = service.Group 146 } 147 if len(service.Interface) > 0 { 148 request.Attachments[INTERFACE_KEY] = service.Interface 149 } 150 if service.Timeout != 0 { 151 request.Attachments[TIMEOUT_KEY] = strconv.Itoa(int(service.Timeout / time.Millisecond)) 152 } 153 154 err = encoder.Encode(request.Attachments) 155 return encoder.Buffer(), err 156 } 157 158 var versionInt = make(map[string]int) 159 160 // https://github.com/apache/dubbo/blob/dubbo-2.7.1/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java#L96 161 // isSupportResponseAttachment is for compatibility among some dubbo version 162 func isSupportResponseAttachment(version string) bool { 163 if version == "" { 164 return false 165 } 166 167 v, ok := versionInt[version] 168 if !ok { 169 v = version2Int(version) 170 if v == -1 { 171 return false 172 } 173 } 174 175 if v >= 2001000 && v <= 2060200 { // 2.0.10 ~ 2.6.2 176 return false 177 } 178 return v >= LOWEST_VERSION_FOR_RESPONSE_ATTACHMENT 179 } 180 181 func version2Int(version string) int { 182 v := 0 183 varr := strings.Split(version, ".") 184 length := len(varr) 185 for key, value := range varr { 186 v0, err := strconv.Atoi(value) 187 if err != nil { 188 return -1 189 } 190 v += v0 * int(math.Pow10((length-key-1)*2)) 191 } 192 if length == 3 { 193 return v * 100 194 } 195 return v 196 } 197 198 func unmarshalRequestBody(body []byte, p *DubboPackage) error { 199 if p.Body == nil { 200 p.SetBody(make([]interface{}, 7)) 201 } 202 decoder := hessian.NewDecoder(body) 203 var ( 204 err error 205 dubboVersion, target, serviceVersion, method, argsTypes interface{} 206 args []interface{} 207 ) 208 req, ok := p.Body.([]interface{}) 209 if !ok { 210 return perrors.Errorf("@reqObj is not of type: []interface{}") 211 } 212 dubboVersion, err = decoder.Decode() 213 if err != nil { 214 return perrors.WithStack(err) 215 } 216 req[0] = dubboVersion 217 218 target, err = decoder.Decode() 219 if err != nil { 220 return perrors.WithStack(err) 221 } 222 req[1] = target 223 224 serviceVersion, err = decoder.Decode() 225 if err != nil { 226 return perrors.WithStack(err) 227 } 228 req[2] = serviceVersion 229 230 method, err = decoder.Decode() 231 if err != nil { 232 return perrors.WithStack(err) 233 } 234 req[3] = method 235 236 argsTypes, err = decoder.Decode() 237 if err != nil { 238 return perrors.WithStack(err) 239 } 240 req[4] = argsTypes 241 242 ats := hessian.DescRegex.FindAllString(argsTypes.(string), -1) 243 var arg interface{} 244 for i := 0; i < len(ats); i++ { 245 arg, err = decoder.Decode() 246 if err != nil { 247 return perrors.WithStack(err) 248 } 249 args = append(args, arg) 250 } 251 req[5] = args 252 253 attachments, err := decoder.Decode() 254 if err != nil { 255 return perrors.WithStack(err) 256 } 257 258 if attachments == nil || attachments == "" { 259 attachments = map[interface{}]interface{}{constant.InterfaceKey: target} 260 } 261 262 if v, ok := attachments.(map[interface{}]interface{}); ok { 263 v[DUBBO_VERSION_KEY] = dubboVersion 264 req[6] = ToMapStringInterface(v) 265 buildServerSidePackageBody(p) 266 return nil 267 } 268 return perrors.Errorf("get wrong attachments: %+v", attachments) 269 } 270 271 func unmarshalResponseBody(body []byte, p *DubboPackage) error { 272 decoder := hessian.NewDecoder(body) 273 rspType, err := decoder.Decode() 274 if p.Body == nil { 275 p.SetBody(&ResponsePayload{}) 276 } 277 if err != nil { 278 return perrors.WithStack(err) 279 } 280 response := EnsureResponsePayload(p.Body) 281 282 switch rspType { 283 case RESPONSE_WITH_EXCEPTION, RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS: 284 expt, err := decoder.Decode() 285 if err != nil { 286 return perrors.WithStack(err) 287 } 288 if rspType == RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS { 289 attachments, err := decoder.Decode() 290 if err != nil { 291 return perrors.WithStack(err) 292 } 293 if v, ok := attachments.(map[interface{}]interface{}); ok { 294 atta := ToMapStringInterface(v) 295 response.Attachments = atta 296 } else { 297 return perrors.Errorf("get wrong attachments: %+v", attachments) 298 } 299 } 300 301 if e, ok := expt.(error); ok { 302 response.Exception = e 303 } else { 304 response.Exception = perrors.Errorf("got exception: %+v", expt) 305 } 306 return nil 307 308 case RESPONSE_VALUE, RESPONSE_VALUE_WITH_ATTACHMENTS: 309 rsp, err := decoder.Decode() 310 if err != nil { 311 return perrors.WithStack(err) 312 } 313 if rspType == RESPONSE_VALUE_WITH_ATTACHMENTS { 314 attachments, err := decoder.Decode() 315 if err != nil { 316 return perrors.WithStack(err) 317 } 318 if v, ok := attachments.(map[interface{}]interface{}); ok { 319 atta := ToMapStringInterface(v) 320 response.Attachments = atta 321 } else { 322 return perrors.Errorf("get wrong attachments: %+v", attachments) 323 } 324 } 325 326 return perrors.WithStack(hessian.ReflectResponse(rsp, response.RspObj)) 327 328 case RESPONSE_NULL_VALUE, RESPONSE_NULL_VALUE_WITH_ATTACHMENTS: 329 if rspType == RESPONSE_NULL_VALUE_WITH_ATTACHMENTS { 330 attachments, err := decoder.Decode() 331 if err != nil { 332 return perrors.WithStack(err) 333 } 334 if v, ok := attachments.(map[interface{}]interface{}); ok { 335 atta := ToMapStringInterface(v) 336 response.Attachments = atta 337 } else { 338 return perrors.Errorf("get wrong attachments: %+v", attachments) 339 } 340 } 341 return nil 342 } 343 return nil 344 } 345 346 func buildServerSidePackageBody(pkg *DubboPackage) { 347 req := pkg.GetBody().([]interface{}) // length of body should be 7 348 if len(req) > 0 { 349 var dubboVersion, argsTypes string 350 var args []interface{} 351 var attachments map[string]interface{} 352 svc := Service{} 353 if req[0] != nil { 354 dubboVersion = req[0].(string) 355 } 356 if req[1] != nil { 357 svc.Path = req[1].(string) 358 } 359 if req[2] != nil { 360 svc.Version = req[2].(string) 361 } 362 if req[3] != nil { 363 svc.Method = req[3].(string) 364 } 365 if req[4] != nil { 366 argsTypes = req[4].(string) 367 } 368 if req[5] != nil { 369 args = req[5].([]interface{}) 370 } 371 if req[6] != nil { 372 attachments = req[6].(map[string]interface{}) 373 } 374 if svc.Path == "" && attachments[constant.PathKey] != nil && len(attachments[constant.PathKey].(string)) > 0 { 375 svc.Path = attachments[constant.PathKey].(string) 376 } 377 if _, ok := attachments[constant.InterfaceKey]; ok { 378 svc.Interface = attachments[constant.InterfaceKey].(string) 379 } else { 380 svc.Interface = svc.Path 381 } 382 if _, ok := attachments[constant.GroupKey]; ok { 383 svc.Group = attachments[constant.GroupKey].(string) 384 } 385 pkg.SetService(svc) 386 pkg.SetBody(map[string]interface{}{ 387 "dubboVersion": dubboVersion, 388 "argsTypes": argsTypes, 389 "args": args, 390 "service": common.ServiceMap.GetService(DUBBO, svc.Interface, svc.Group, svc.Version), // path as a key 391 "attachments": attachments, 392 }) 393 } 394 } 395 396 func GetArgsTypeList(args []interface{}) (string, error) { 397 var ( 398 typ string 399 types string 400 ) 401 402 for i := range args { 403 typ = getArgType(args[i]) 404 if typ == "" { 405 return types, perrors.Errorf("cat not get arg %#v type", args[i]) 406 } 407 if !strings.Contains(typ, ".") { 408 types += typ 409 } else if strings.Index(typ, "[") == 0 { 410 types += strings.Replace(typ, ".", "/", -1) 411 } else { 412 // java.util.List -> Ljava/util/List; 413 types += "L" + strings.Replace(typ, ".", "/", -1) + ";" 414 } 415 } 416 417 return types, nil 418 } 419 420 func getArgType(v interface{}) string { 421 if v == nil { 422 return "V" 423 } 424 425 switch v := v.(type) { 426 // Serialized tags for base types 427 case nil: 428 return "V" 429 case bool: 430 return "Z" 431 case []bool: 432 return "[Z" 433 case byte: 434 return "B" 435 case []byte: 436 return "[B" 437 case int8: 438 return "B" 439 case []int8: 440 return "[B" 441 case int16: 442 return "S" 443 case []int16: 444 return "[S" 445 case uint16: // Equivalent to Char of Java 446 return "C" 447 case []uint16: 448 return "[C" 449 // case rune: 450 // return "C" 451 case int: 452 return "J" 453 case []int: 454 return "[J" 455 case int32: 456 return "I" 457 case []int32: 458 return "[I" 459 case int64: 460 return "J" 461 case []int64: 462 return "[J" 463 case time.Time: 464 return "java.util.Date" 465 case []time.Time: 466 return "[Ljava.util.Date" 467 case float32: 468 return "F" 469 case []float32: 470 return "[F" 471 case float64: 472 return "D" 473 case []float64: 474 return "[D" 475 case string: 476 return "java.lang.String" 477 case []string: 478 return "[Ljava.lang.String;" 479 case []hessian.Object: 480 return "[Ljava.lang.Object;" 481 case map[interface{}]interface{}: 482 // return "java.util.HashMap" 483 return "java.util.Map" 484 case hessian.POJOEnum: 485 return v.(hessian.POJOEnum).JavaClassName() 486 case *int8: 487 return "java.lang.Byte" 488 case *int16: 489 return "java.lang.Short" 490 case *uint16: 491 return "java.lang.Character" 492 case *int: 493 return "java.lang.Long" 494 case *int32: 495 return "java.lang.Integer" 496 case *int64: 497 return "java.lang.Long" 498 case *float32: 499 return "java.lang.Float" 500 case *float64: 501 return "java.lang.Double" 502 // Serialized tags for complex types 503 default: 504 t := reflect.TypeOf(v) 505 if reflect.Ptr == t.Kind() { 506 t = reflect.TypeOf(reflect.ValueOf(v).Elem()) 507 } 508 switch t.Kind() { 509 case reflect.Struct: 510 p, ok := v.(hessian.Param) 511 if ok { 512 return p.JavaParamName() 513 } 514 v, ok := v.(hessian.POJO) 515 if ok { 516 return v.JavaClassName() 517 } 518 return "java.lang.Object" 519 case reflect.Slice, reflect.Array: 520 if t.Elem().Kind() == reflect.Struct { 521 return "[Ljava.lang.Object;" 522 } 523 // return "java.util.ArrayList" 524 return "java.util.List" 525 case reflect.Map: // Enter here, map may be map[string]int 526 return "java.util.Map" 527 default: 528 return "" 529 } 530 } 531 532 // unreachable 533 // return "java.lang.RuntimeException" 534 } 535 536 func ToMapStringInterface(origin map[interface{}]interface{}) map[string]interface{} { 537 dest := make(map[string]interface{}, len(origin)) 538 for k, v := range origin { 539 if kv, ok := k.(string); ok { 540 if v == nil { 541 dest[kv] = "" 542 continue 543 } 544 dest[kv] = v 545 } 546 } 547 return dest 548 } 549 550 func init() { 551 SetSerializer("hessian2", HessianSerializer{}) 552 }