dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/dubbo/hessian2/hessian_dubbo.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 hessian2
    19  
    20  import (
    21  	"bufio"
    22  	"encoding/binary"
    23  	"time"
    24  )
    25  
    26  import (
    27  	"github.com/apache/dubbo-go-hessian2"
    28  
    29  	perrors "github.com/pkg/errors"
    30  )
    31  
    32  // enum part
    33  const (
    34  	PackageError              = PackageType(0x01)
    35  	PackageRequest            = PackageType(0x02)
    36  	PackageResponse           = PackageType(0x04)
    37  	PackageHeartbeat          = PackageType(0x08)
    38  	PackageRequest_TwoWay     = PackageType(0x10)
    39  	PackageResponse_Exception = PackageType(0x20)
    40  	PackageType_BitSize       = 0x2f
    41  )
    42  
    43  // PackageType nolint
    44  type PackageType int
    45  
    46  // DubboHeader dubbo header
    47  type DubboHeader struct {
    48  	SerialID       byte
    49  	Type           PackageType
    50  	ID             int64
    51  	BodyLen        int
    52  	ResponseStatus byte
    53  }
    54  
    55  // Service defines service instance
    56  type Service struct {
    57  	Path      string
    58  	Interface string
    59  	Group     string
    60  	Version   string
    61  	Method    string
    62  	Timeout   time.Duration // request timeout
    63  }
    64  
    65  // HessianCodec defines hessian codec
    66  type HessianCodec struct {
    67  	pkgType PackageType
    68  	reader  *bufio.Reader
    69  	bodyLen int
    70  }
    71  
    72  // NewHessianCodec generate a new hessian codec instance
    73  func NewHessianCodec(reader *bufio.Reader) *HessianCodec {
    74  	return &HessianCodec{
    75  		reader: reader,
    76  	}
    77  }
    78  
    79  // NewHessianCodec generate a new hessian codec instance
    80  func NewHessianCodecCustom(pkgType PackageType, reader *bufio.Reader, bodyLen int) *HessianCodec {
    81  	return &HessianCodec{
    82  		pkgType: pkgType,
    83  		reader:  reader,
    84  		bodyLen: bodyLen,
    85  	}
    86  }
    87  
    88  func (h *HessianCodec) Write(service Service, header DubboHeader, body interface{}) ([]byte, error) {
    89  	switch header.Type {
    90  	case PackageHeartbeat:
    91  		if header.ResponseStatus == Zero {
    92  			return packRequest(service, header, body)
    93  		}
    94  		return packResponse(header, body)
    95  
    96  	case PackageRequest, PackageRequest_TwoWay:
    97  		return packRequest(service, header, body)
    98  
    99  	case PackageResponse:
   100  		return packResponse(header, body)
   101  
   102  	default:
   103  		return nil, perrors.Errorf("Unrecognized message type: %v", header.Type)
   104  	}
   105  
   106  	// unreachable return nil, nil
   107  }
   108  
   109  // ReadHeader uses hessian codec to read dubbo header
   110  func (h *HessianCodec) ReadHeader(header *DubboHeader) error {
   111  	var err error
   112  
   113  	if h.reader.Size() < HEADER_LENGTH {
   114  		return ErrHeaderNotEnough
   115  	}
   116  	buf, err := h.reader.Peek(HEADER_LENGTH)
   117  	if err != nil { // this is impossible
   118  		return perrors.WithStack(err)
   119  	}
   120  	_, err = h.reader.Discard(HEADER_LENGTH)
   121  	if err != nil { // this is impossible
   122  		return perrors.WithStack(err)
   123  	}
   124  
   125  	//// read header
   126  
   127  	if buf[0] != MAGIC_HIGH && buf[1] != MAGIC_LOW {
   128  		return ErrIllegalPackage
   129  	}
   130  
   131  	// Header{serialization id(5 bit), event, two way, req/response}
   132  	if header.SerialID = buf[2] & SERIAL_MASK; header.SerialID == Zero {
   133  		return perrors.Errorf("serialization ID:%v", header.SerialID)
   134  	}
   135  
   136  	flag := buf[2] & FLAG_EVENT
   137  	if flag != Zero {
   138  		header.Type |= PackageHeartbeat
   139  	}
   140  	flag = buf[2] & FLAG_REQUEST
   141  	if flag != Zero {
   142  		header.Type |= PackageRequest
   143  		flag = buf[2] & FLAG_TWOWAY
   144  		if flag != Zero {
   145  			header.Type |= PackageRequest_TwoWay
   146  		}
   147  	} else {
   148  		header.Type |= PackageResponse
   149  		header.ResponseStatus = buf[3]
   150  		if header.ResponseStatus != Response_OK {
   151  			header.Type |= PackageResponse_Exception
   152  		}
   153  	}
   154  
   155  	// Header{req id}
   156  	header.ID = int64(binary.BigEndian.Uint64(buf[4:]))
   157  
   158  	// Header{body len}
   159  	header.BodyLen = int(binary.BigEndian.Uint32(buf[12:]))
   160  	if header.BodyLen < 0 {
   161  		return ErrIllegalPackage
   162  	}
   163  
   164  	h.pkgType = header.Type
   165  	h.bodyLen = header.BodyLen
   166  
   167  	if h.reader.Buffered() < h.bodyLen {
   168  		return ErrBodyNotEnough
   169  	}
   170  
   171  	return perrors.WithStack(err)
   172  }
   173  
   174  // ReadBody uses hessian codec to read response body
   175  func (h *HessianCodec) ReadBody(rspObj interface{}) error {
   176  	if h.reader.Buffered() < h.bodyLen {
   177  		return ErrBodyNotEnough
   178  	}
   179  	buf, err := h.reader.Peek(h.bodyLen)
   180  	if err != nil {
   181  		return perrors.WithStack(err)
   182  	}
   183  	_, err = h.reader.Discard(h.bodyLen)
   184  	if err != nil { // this is impossible
   185  		return perrors.WithStack(err)
   186  	}
   187  
   188  	switch h.pkgType & PackageType_BitSize {
   189  	case PackageResponse | PackageHeartbeat | PackageResponse_Exception, PackageResponse | PackageResponse_Exception:
   190  		decoder := hessian.NewDecoder(buf[:])
   191  		exception, exceptionErr := decoder.Decode()
   192  		if exceptionErr != nil {
   193  			return perrors.WithStack(exceptionErr)
   194  		}
   195  		rsp, ok := rspObj.(*DubboResponse)
   196  		if !ok {
   197  			return perrors.Errorf("java exception:%s", exception.(string))
   198  		}
   199  		rsp.Exception = perrors.Errorf("java exception:%s", exception.(string))
   200  		return nil
   201  	case PackageRequest | PackageHeartbeat, PackageResponse | PackageHeartbeat:
   202  	case PackageRequest:
   203  		if rspObj != nil {
   204  			if err = unpackRequestBody(hessian.NewDecoder(buf[:]), rspObj); err != nil {
   205  				return perrors.WithStack(err)
   206  			}
   207  		}
   208  	case PackageResponse:
   209  		if rspObj != nil {
   210  			if err = unpackResponseBody(hessian.NewDecoder(buf[:]), rspObj); err != nil {
   211  				return perrors.WithStack(err)
   212  			}
   213  		}
   214  	}
   215  
   216  	return nil
   217  }
   218  
   219  // ignore body, but only read attachments
   220  func (h *HessianCodec) ReadAttachments() (map[string]interface{}, error) {
   221  	if h.reader.Buffered() < h.bodyLen {
   222  		return nil, ErrBodyNotEnough
   223  	}
   224  	buf, err := h.reader.Peek(h.bodyLen)
   225  	if err != nil {
   226  		return nil, perrors.WithStack(err)
   227  	}
   228  	_, err = h.reader.Discard(h.bodyLen)
   229  	if err != nil { // this is impossible
   230  		return nil, perrors.WithStack(err)
   231  	}
   232  
   233  	switch h.pkgType & PackageType_BitSize {
   234  	case PackageRequest:
   235  		rspObj := make([]interface{}, 7)
   236  		if err = unpackRequestBody(hessian.NewDecoderWithSkip(buf[:]), rspObj); err != nil {
   237  			return nil, perrors.WithStack(err)
   238  		}
   239  		return rspObj[6].(map[string]interface{}), nil
   240  	case PackageResponse:
   241  		rspObj := &DubboResponse{}
   242  		if err = unpackResponseBody(hessian.NewDecoderWithSkip(buf[:]), rspObj); err != nil {
   243  			return nil, perrors.WithStack(err)
   244  		}
   245  		return rspObj.Attachments, nil
   246  	}
   247  
   248  	return nil, nil
   249  }