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 }