dubbo.apache.org/dubbo-go/v3@v3.1.1/remoting/getty/dubbo_codec_for_test.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 getty 19 20 // copy from dubbo/dubbo_codec.go . 21 // it is used to unit test. 22 import ( 23 "bytes" 24 "strconv" 25 "time" 26 ) 27 28 import ( 29 hessian "github.com/apache/dubbo-go-hessian2" 30 31 perrors "github.com/pkg/errors" 32 ) 33 34 import ( 35 "dubbo.apache.org/dubbo-go/v3/common/constant" 36 "dubbo.apache.org/dubbo-go/v3/protocol" 37 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo/impl" 38 "dubbo.apache.org/dubbo-go/v3/protocol/invocation" 39 "dubbo.apache.org/dubbo-go/v3/remoting" 40 ) 41 42 func init() { 43 codec := &DubboTestCodec{} 44 remoting.RegistryCodec("dubbo", codec) 45 } 46 47 type DubboTestCodec struct{} 48 49 // encode request for transport 50 func (c *DubboTestCodec) EncodeRequest(request *remoting.Request) (*bytes.Buffer, error) { 51 if request.Event { 52 return c.encodeHeartbeartReqeust(request) 53 } 54 55 invoc, ok := request.Data.(*invocation.RPCInvocation) 56 if !ok { 57 return nil, perrors.Errorf("encode request failed for parameter type :%+v", request) 58 } 59 tmpInvocation := invoc 60 61 svc := impl.Service{} 62 svc.Path = tmpInvocation.GetAttachmentWithDefaultValue(constant.PathKey, "") 63 svc.Interface = tmpInvocation.GetAttachmentWithDefaultValue(constant.InterfaceKey, "") 64 svc.Version = tmpInvocation.GetAttachmentWithDefaultValue(constant.VersionKey, "") 65 svc.Group = tmpInvocation.GetAttachmentWithDefaultValue(constant.GroupKey, "") 66 svc.Method = tmpInvocation.MethodName() 67 timeout, err := strconv.Atoi(tmpInvocation.GetAttachmentWithDefaultValue(constant.TimeoutKey, strconv.Itoa(constant.DefaultRemotingTimeout))) 68 if err != nil { 69 // it will be wrapped in readwrite.Write . 70 return nil, perrors.WithStack(err) 71 } 72 svc.Timeout = time.Duration(timeout) 73 74 header := impl.DubboHeader{} 75 serialization := tmpInvocation.GetAttachmentWithDefaultValue(constant.SerializationKey, constant.Hessian2Serialization) 76 if serialization == constant.ProtobufSerialization { 77 header.SerialID = constant.SProto 78 } else { 79 header.SerialID = constant.SHessian2 80 } 81 header.ID = request.ID 82 if request.TwoWay { 83 header.Type = impl.PackageRequest_TwoWay 84 } else { 85 header.Type = impl.PackageRequest 86 } 87 88 pkg := &impl.DubboPackage{ 89 Header: header, 90 Service: svc, 91 Body: impl.NewRequestPayload(tmpInvocation.Arguments(), tmpInvocation.Attachments()), 92 Err: nil, 93 Codec: impl.NewDubboCodec(nil), 94 } 95 96 if err := impl.LoadSerializer(pkg); err != nil { 97 return nil, perrors.WithStack(err) 98 } 99 100 return pkg.Marshal() 101 } 102 103 // encode heartbeat request 104 func (c *DubboTestCodec) encodeHeartbeartReqeust(request *remoting.Request) (*bytes.Buffer, error) { 105 header := impl.DubboHeader{ 106 Type: impl.PackageHeartbeat, 107 SerialID: constant.SHessian2, 108 ID: request.ID, 109 } 110 111 pkg := &impl.DubboPackage{ 112 Header: header, 113 Service: impl.Service{}, 114 Body: impl.NewRequestPayload([]interface{}{}, nil), 115 Err: nil, 116 Codec: impl.NewDubboCodec(nil), 117 } 118 119 if err := impl.LoadSerializer(pkg); err != nil { 120 return nil, err 121 } 122 return pkg.Marshal() 123 } 124 125 // encode response 126 func (c *DubboTestCodec) EncodeResponse(response *remoting.Response) (*bytes.Buffer, error) { 127 ptype := impl.PackageResponse 128 if response.IsHeartbeat() { 129 ptype = impl.PackageHeartbeat 130 } 131 resp := &impl.DubboPackage{ 132 Header: impl.DubboHeader{ 133 SerialID: response.SerialID, 134 Type: ptype, 135 ID: response.ID, 136 ResponseStatus: response.Status, 137 }, 138 } 139 if !response.IsHeartbeat() { 140 resp.Body = &impl.ResponsePayload{ 141 RspObj: response.Result.(protocol.RPCResult).Rest, 142 Exception: response.Result.(protocol.RPCResult).Err, 143 Attachments: response.Result.(protocol.RPCResult).Attrs, 144 } 145 } 146 147 codec := impl.NewDubboCodec(nil) 148 149 pkg, err := codec.Encode(*resp) 150 if err != nil { 151 return nil, perrors.WithStack(err) 152 } 153 154 return bytes.NewBuffer(pkg), nil 155 } 156 157 // Decode data, including request and response. 158 func (c *DubboTestCodec) Decode(data []byte) (*remoting.DecodeResult, int, error) { 159 if c.isRequest(data) { 160 req, len, err := c.decodeRequest(data) 161 if err != nil { 162 return &remoting.DecodeResult{}, len, perrors.WithStack(err) 163 } 164 return &remoting.DecodeResult{IsRequest: true, Result: req}, len, perrors.WithStack(err) 165 } else { 166 resp, len, err := c.decodeResponse(data) 167 if err != nil { 168 return &remoting.DecodeResult{}, len, perrors.WithStack(err) 169 } 170 return &remoting.DecodeResult{IsRequest: false, Result: resp}, len, perrors.WithStack(err) 171 } 172 } 173 174 func (c *DubboTestCodec) isRequest(data []byte) bool { 175 return data[2]&byte(0x80) != 0x00 176 } 177 178 // decode request 179 func (c *DubboTestCodec) decodeRequest(data []byte) (*remoting.Request, int, error) { 180 var request *remoting.Request = nil 181 buf := bytes.NewBuffer(data) 182 pkg := impl.NewDubboPackage(buf) 183 pkg.SetBody(make([]interface{}, 7)) 184 err := pkg.Unmarshal() 185 if err != nil { 186 originErr := perrors.Cause(err) 187 if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { 188 // FIXME 189 return nil, 0, originErr 190 } 191 return request, 0, perrors.WithStack(err) 192 } 193 request = &remoting.Request{ 194 ID: pkg.Header.ID, 195 SerialID: pkg.Header.SerialID, 196 TwoWay: pkg.Header.Type&impl.PackageRequest_TwoWay != 0x00, 197 Event: pkg.Header.Type&impl.PackageHeartbeat != 0x00, 198 } 199 if (pkg.Header.Type & impl.PackageHeartbeat) == 0x00 { 200 // convert params of request 201 req := pkg.Body.(map[string]interface{}) 202 203 // invocation := request.Data.(*invocation.RPCInvocation) 204 var methodName string 205 var args []interface{} 206 attachments := make(map[string]interface{}) 207 if req[impl.DubboVersionKey] != nil { 208 // dubbo version 209 request.Version = req[impl.DubboVersionKey].(string) 210 } 211 // path 212 attachments[constant.PathKey] = pkg.Service.Path 213 // version 214 attachments[constant.VersionKey] = pkg.Service.Version 215 // method 216 methodName = pkg.Service.Method 217 args = req[impl.ArgsKey].([]interface{}) 218 attachments = req[impl.AttachmentsKey].(map[string]interface{}) 219 invoc := invocation.NewRPCInvocationWithOptions(invocation.WithAttachments(attachments), 220 invocation.WithArguments(args), invocation.WithMethodName(methodName)) 221 request.Data = invoc 222 223 } 224 return request, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil 225 } 226 227 // decode response 228 func (c *DubboTestCodec) decodeResponse(data []byte) (*remoting.Response, int, error) { 229 buf := bytes.NewBuffer(data) 230 pkg := impl.NewDubboPackage(buf) 231 err := pkg.Unmarshal() 232 if err != nil { 233 originErr := perrors.Cause(err) 234 // if the data is very big, so the receive need much times. 235 if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { 236 return nil, 0, originErr 237 } 238 return nil, 0, perrors.WithStack(err) 239 } 240 response := &remoting.Response{ 241 ID: pkg.Header.ID, 242 // Version: pkg.Header., 243 SerialID: pkg.Header.SerialID, 244 Status: pkg.Header.ResponseStatus, 245 Event: (pkg.Header.Type & impl.PackageHeartbeat) != 0, 246 } 247 var error error 248 if pkg.Header.Type&impl.PackageHeartbeat != 0x00 { 249 if pkg.Header.Type&impl.PackageResponse != 0x00 { 250 if pkg.Err != nil { 251 error = pkg.Err 252 } 253 } else { 254 response.Status = hessian.Response_OK 255 // reply(session, p, hessian.PackageHeartbeat) 256 } 257 return response, hessian.HEADER_LENGTH + pkg.Header.BodyLen, error 258 } 259 rpcResult := &protocol.RPCResult{} 260 response.Result = rpcResult 261 if pkg.Header.Type&impl.PackageRequest == 0x00 { 262 if pkg.Err != nil { 263 rpcResult.Err = pkg.Err 264 } else if pkg.Body.(*impl.ResponsePayload).Exception != nil { 265 rpcResult.Err = pkg.Body.(*impl.ResponsePayload).Exception 266 response.Error = rpcResult.Err 267 } 268 rpcResult.Attrs = pkg.Body.(*impl.ResponsePayload).Attachments 269 rpcResult.Rest = pkg.Body.(*impl.ResponsePayload).RspObj 270 } 271 272 return response, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil 273 }