dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/dubbo/impl/codec.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 "bufio" 22 "encoding/binary" 23 ) 24 25 import ( 26 hessian "github.com/apache/dubbo-go-hessian2" 27 28 "github.com/dubbogo/gost/log/logger" 29 30 perrors "github.com/pkg/errors" 31 ) 32 33 import ( 34 "dubbo.apache.org/dubbo-go/v3/common/constant" 35 "dubbo.apache.org/dubbo-go/v3/remoting" 36 ) 37 38 type ProtocolCodec struct { 39 reader *bufio.Reader 40 pkgType PackageType 41 bodyLen int 42 serializer Serializer 43 headerRead bool 44 } 45 46 func (c *ProtocolCodec) ReadHeader(header *DubboHeader) error { 47 var err error 48 if c.reader.Size() < HEADER_LENGTH { 49 return hessian.ErrHeaderNotEnough 50 } 51 buf, err := c.reader.Peek(HEADER_LENGTH) 52 if err != nil { // this is impossible 53 return perrors.WithStack(err) 54 } 55 _, err = c.reader.Discard(HEADER_LENGTH) 56 if err != nil { // this is impossible 57 return perrors.WithStack(err) 58 } 59 60 //// read header 61 if buf[0] != MAGIC_HIGH && buf[1] != MAGIC_LOW { 62 return hessian.ErrIllegalPackage 63 } 64 65 // Header{serialization id(5 bit), event, two way, req/response} 66 if header.SerialID = buf[2] & SERIAL_MASK; header.SerialID == Zero { 67 return perrors.Errorf("serialization ID:%v", header.SerialID) 68 } 69 70 flag := buf[2] & FLAG_EVENT 71 if flag != Zero { 72 header.Type |= PackageHeartbeat 73 } 74 flag = buf[2] & FLAG_REQUEST 75 if flag != Zero { 76 header.Type |= PackageRequest 77 flag = buf[2] & FLAG_TWOWAY 78 if flag != Zero { 79 header.Type |= PackageRequest_TwoWay 80 } 81 } else { 82 header.Type |= PackageResponse 83 header.ResponseStatus = buf[3] 84 if header.ResponseStatus != Response_OK { 85 header.Type |= PackageResponse_Exception 86 } 87 } 88 89 // Header{req id} 90 header.ID = int64(binary.BigEndian.Uint64(buf[4:])) 91 92 // Header{body len} 93 header.BodyLen = int(binary.BigEndian.Uint32(buf[12:])) 94 if header.BodyLen < 0 { 95 return hessian.ErrIllegalPackage 96 } 97 98 c.pkgType = header.Type 99 c.bodyLen = header.BodyLen 100 101 if c.reader.Buffered() < c.bodyLen { 102 return hessian.ErrBodyNotEnough 103 } 104 c.headerRead = true 105 return perrors.WithStack(err) 106 } 107 108 func (c *ProtocolCodec) EncodeHeader(p DubboPackage) []byte { 109 header := p.Header 110 bs := make([]byte, 0) 111 switch header.Type { 112 case PackageHeartbeat: 113 if header.ResponseStatus == Zero { 114 bs = append(bs, hessian.DubboRequestHeartbeatHeader[:]...) 115 } else { 116 bs = append(bs, hessian.DubboResponseHeartbeatHeader[:]...) 117 } 118 case PackageResponse: 119 bs = append(bs, hessian.DubboResponseHeaderBytes[:]...) 120 if header.ResponseStatus != 0 { 121 bs[3] = header.ResponseStatus 122 } 123 case PackageRequest_TwoWay: 124 bs = append(bs, hessian.DubboRequestHeaderBytesTwoWay[:]...) 125 } 126 bs[2] |= header.SerialID & hessian.SERIAL_MASK 127 binary.BigEndian.PutUint64(bs[4:], uint64(header.ID)) 128 return bs 129 } 130 131 func (c *ProtocolCodec) Encode(p DubboPackage) ([]byte, error) { 132 // header 133 if c.serializer == nil { 134 return nil, perrors.New("serializer should not be nil") 135 } 136 header := p.Header 137 switch header.Type { 138 case PackageHeartbeat: 139 if header.ResponseStatus == Zero { 140 return packRequest(p, c.serializer) 141 } 142 return packResponse(p, c.serializer) 143 144 case PackageRequest, PackageRequest_TwoWay: 145 return packRequest(p, c.serializer) 146 147 case PackageResponse: 148 return packResponse(p, c.serializer) 149 150 default: 151 return nil, perrors.Errorf("Unrecognized message type: %v", header.Type) 152 } 153 } 154 155 func (c *ProtocolCodec) Decode(p *DubboPackage) error { 156 if !c.headerRead { 157 if err := c.ReadHeader(&p.Header); err != nil { 158 return err 159 } 160 } 161 if c.reader.Size() < p.GetBodyLen() { 162 return hessian.ErrBodyNotEnough 163 } 164 body, err := c.reader.Peek(p.GetBodyLen()) 165 if err != nil { 166 return err 167 } 168 if p.IsResponseWithException() { 169 logger.Infof("response with exception: %+v", p.Header) 170 decoder := hessian.NewDecoder(body) 171 p.Body = &ResponsePayload{} 172 exception, err := decoder.Decode() 173 if err != nil { 174 return perrors.WithStack(err) 175 } 176 p.Body.(*ResponsePayload).Exception = perrors.Errorf("java exception:%s", exception.(string)) 177 return nil 178 } else if p.IsHeartBeat() { 179 // heartbeat no need to unmarshal contents 180 return nil 181 } 182 if c.serializer == nil { 183 return perrors.New("Codec serializer is nil") 184 } 185 if p.IsResponse() { 186 p.Body = &ResponsePayload{ 187 RspObj: remoting.GetPendingResponse(remoting.SequenceType(p.Header.ID)).Reply, 188 } 189 } 190 return c.serializer.Unmarshal(body, p) 191 } 192 193 func (c *ProtocolCodec) SetSerializer(serializer Serializer) { 194 c.serializer = serializer 195 } 196 197 func packRequest(p DubboPackage, serializer Serializer) ([]byte, error) { 198 var ( 199 byteArray []byte 200 pkgLen int 201 ) 202 203 header := p.Header 204 205 ////////////////////////////////////////// 206 // byteArray 207 ////////////////////////////////////////// 208 // magic 209 switch header.Type { 210 case PackageHeartbeat: 211 byteArray = append(byteArray, DubboRequestHeartbeatHeader[:]...) 212 case PackageRequest_TwoWay: 213 byteArray = append(byteArray, DubboRequestHeaderBytesTwoWay[:]...) 214 default: 215 byteArray = append(byteArray, DubboRequestHeaderBytes[:]...) 216 } 217 218 // serialization id, two way flag, event, request/response flag 219 // SerialID is id of serialization approach in java dubbo 220 byteArray[2] |= header.SerialID & SERIAL_MASK 221 // request id 222 binary.BigEndian.PutUint64(byteArray[4:], uint64(header.ID)) 223 224 ////////////////////////////////////////// 225 // body 226 ////////////////////////////////////////// 227 if p.IsHeartBeat() { 228 byteArray = append(byteArray, byte('N')) 229 pkgLen = 1 230 } else { 231 body, err := serializer.Marshal(p) 232 if err != nil { 233 return nil, err 234 } 235 pkgLen = len(body) 236 if pkgLen > int(DEFAULT_LEN) { // recommand 8M 237 logger.Warnf("Data length %d too large, recommand max payload %d. "+ 238 "Dubbo java can't handle the package whose size is greater than %d!!!", pkgLen, DEFAULT_LEN, DEFAULT_LEN) 239 } 240 byteArray = append(byteArray, body...) 241 } 242 binary.BigEndian.PutUint32(byteArray[12:], uint32(pkgLen)) 243 return byteArray, nil 244 } 245 246 func packResponse(p DubboPackage, serializer Serializer) ([]byte, error) { 247 var byteArray []byte 248 header := p.Header 249 hb := p.IsHeartBeat() 250 251 // magic 252 if hb { 253 byteArray = append(byteArray, DubboResponseHeartbeatHeader[:]...) 254 } else { 255 byteArray = append(byteArray, DubboResponseHeaderBytes[:]...) 256 } 257 // set serialID, identify serialization types, eg: fastjson->6, hessian2->2 258 byteArray[2] |= header.SerialID & SERIAL_MASK 259 // response status 260 if header.ResponseStatus != 0 { 261 byteArray[3] = header.ResponseStatus 262 } 263 264 // request id 265 binary.BigEndian.PutUint64(byteArray[4:], uint64(header.ID)) 266 267 // body 268 body, err := serializer.Marshal(p) 269 if err != nil { 270 return nil, err 271 } 272 273 pkgLen := len(body) 274 if pkgLen > int(DEFAULT_LEN) { // recommand 8M 275 logger.Warnf("Data length %d too large, recommand max payload %d. "+ 276 "Dubbo java can't handle the package whose size is greater than %d!!!", pkgLen, DEFAULT_LEN, DEFAULT_LEN) 277 } 278 // byteArray{body length} 279 binary.BigEndian.PutUint32(byteArray[12:], uint32(pkgLen)) 280 byteArray = append(byteArray, body...) 281 return byteArray, nil 282 } 283 284 func NewDubboCodec(reader *bufio.Reader) *ProtocolCodec { 285 s, _ := GetSerializerById(constant.SHessian2) 286 return &ProtocolCodec{ 287 reader: reader, 288 pkgType: 0, 289 bodyLen: 0, 290 headerRead: false, 291 serializer: s, 292 } 293 }