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  }