/proc/self/cwd/source/extensions/filters/network/dubbo_proxy/dubbo_hessian2_serializer_impl.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/extensions/filters/network/dubbo_proxy/dubbo_hessian2_serializer_impl.h" |
2 | | |
3 | | #include "envoy/common/exception.h" |
4 | | |
5 | | #include "source/common/common/assert.h" |
6 | | #include "source/common/common/macros.h" |
7 | | #include "source/extensions/filters/network/dubbo_proxy/hessian_utils.h" |
8 | | #include "source/extensions/filters/network/dubbo_proxy/message_impl.h" |
9 | | |
10 | | #include "hessian2/object.hpp" |
11 | | |
12 | | namespace Envoy { |
13 | | namespace Extensions { |
14 | | namespace NetworkFilters { |
15 | | namespace DubboProxy { |
16 | | |
17 | | std::pair<RpcInvocationSharedPtr, bool> |
18 | | DubboHessian2SerializerImpl::deserializeRpcInvocation(Buffer::Instance& buffer, |
19 | 0 | ContextSharedPtr context) { |
20 | 0 | Hessian2::Decoder decoder(std::make_unique<BufferReader>(buffer)); |
21 | | |
22 | | // TODO(zyfjeff): Add format checker |
23 | 0 | auto dubbo_version = decoder.decode<std::string>(); |
24 | 0 | auto service_name = decoder.decode<std::string>(); |
25 | 0 | auto service_version = decoder.decode<std::string>(); |
26 | 0 | auto method_name = decoder.decode<std::string>(); |
27 | |
|
28 | 0 | if (context->bodySize() < decoder.offset()) { |
29 | 0 | throw EnvoyException(fmt::format("RpcInvocation size({}) larger than body size({})", |
30 | 0 | decoder.offset(), context->bodySize())); |
31 | 0 | } |
32 | | |
33 | 0 | if (dubbo_version == nullptr || service_name == nullptr || service_version == nullptr || |
34 | 0 | method_name == nullptr) { |
35 | 0 | throw EnvoyException(fmt::format("RpcInvocation has no request metadata")); |
36 | 0 | } |
37 | | |
38 | 0 | auto invo = std::make_shared<RpcInvocationImpl>(); |
39 | 0 | invo->setServiceName(*service_name); |
40 | 0 | invo->setServiceVersion(*service_version); |
41 | 0 | invo->setMethodName(*method_name); |
42 | |
|
43 | 0 | size_t parsed_size = context->headerSize() + decoder.offset(); |
44 | |
|
45 | 0 | auto delayed_decoder = std::make_shared<Hessian2::Decoder>( |
46 | 0 | std::make_unique<BufferReader>(context->originMessage(), parsed_size)); |
47 | |
|
48 | 0 | invo->setParametersLazyCallback([delayed_decoder]() -> RpcInvocationImpl::ParametersPtr { |
49 | 0 | auto params = std::make_unique<RpcInvocationImpl::Parameters>(); |
50 | |
|
51 | 0 | if (auto types = delayed_decoder->decode<std::string>(); types != nullptr && !types->empty()) { |
52 | 0 | uint32_t number = HessianUtils::getParametersNumber(*types); |
53 | 0 | for (uint32_t i = 0; i < number; i++) { |
54 | 0 | if (auto result = delayed_decoder->decode<Hessian2::Object>(); result != nullptr) { |
55 | 0 | params->push_back(std::move(result)); |
56 | 0 | } else { |
57 | 0 | throw EnvoyException("Cannot parse RpcInvocation parameter from buffer"); |
58 | 0 | } |
59 | 0 | } |
60 | 0 | } |
61 | 0 | return params; |
62 | 0 | }); |
63 | |
|
64 | 0 | invo->setAttachmentLazyCallback([delayed_decoder]() -> RpcInvocationImpl::AttachmentPtr { |
65 | 0 | size_t offset = delayed_decoder->offset(); |
66 | |
|
67 | 0 | auto result = delayed_decoder->decode<Hessian2::Object>(); |
68 | 0 | if (result != nullptr && result->type() == Hessian2::Object::Type::UntypedMap) { |
69 | 0 | return std::make_unique<RpcInvocationImpl::Attachment>( |
70 | 0 | RpcInvocationImpl::Attachment::MapPtr{ |
71 | 0 | dynamic_cast<RpcInvocationImpl::Attachment::Map*>(result.release())}, |
72 | 0 | offset); |
73 | 0 | } else { |
74 | 0 | return std::make_unique<RpcInvocationImpl::Attachment>( |
75 | 0 | std::make_unique<RpcInvocationImpl::Attachment::Map>(), offset); |
76 | 0 | } |
77 | 0 | }); |
78 | |
|
79 | 0 | return {invo, true}; |
80 | 0 | } |
81 | | |
82 | | std::pair<RpcResultSharedPtr, bool> |
83 | | DubboHessian2SerializerImpl::deserializeRpcResult(Buffer::Instance& buffer, |
84 | 0 | ContextSharedPtr context) { |
85 | 0 | ASSERT(buffer.length() >= context->bodySize()); |
86 | 0 | bool has_value = true; |
87 | |
|
88 | 0 | auto result = std::make_shared<RpcResultImpl>(); |
89 | |
|
90 | 0 | Hessian2::Decoder decoder(std::make_unique<BufferReader>(buffer)); |
91 | 0 | auto type_value = decoder.decode<int32_t>(); |
92 | 0 | if (type_value == nullptr) { |
93 | 0 | throw EnvoyException(fmt::format("Cannot parse RpcResult type from buffer")); |
94 | 0 | } |
95 | | |
96 | 0 | RpcResponseType type = static_cast<RpcResponseType>(*type_value); |
97 | |
|
98 | 0 | switch (type) { |
99 | 0 | case RpcResponseType::ResponseWithException: |
100 | 0 | case RpcResponseType::ResponseWithExceptionWithAttachments: |
101 | 0 | result->setException(true); |
102 | 0 | break; |
103 | 0 | case RpcResponseType::ResponseWithNullValue: |
104 | 0 | has_value = false; |
105 | 0 | FALLTHRU; |
106 | 0 | case RpcResponseType::ResponseNullValueWithAttachments: |
107 | 0 | case RpcResponseType::ResponseWithValue: |
108 | 0 | case RpcResponseType::ResponseValueWithAttachments: |
109 | 0 | result->setException(false); |
110 | 0 | break; |
111 | 0 | default: |
112 | 0 | throw EnvoyException(fmt::format("not supported return type {}", static_cast<uint8_t>(type))); |
113 | 0 | } |
114 | | |
115 | 0 | size_t total_size = decoder.offset(); |
116 | |
|
117 | 0 | if (context->bodySize() < total_size) { |
118 | 0 | throw EnvoyException(fmt::format("RpcResult size({}) large than body size({})", total_size, |
119 | 0 | context->bodySize())); |
120 | 0 | } |
121 | | |
122 | 0 | if (!has_value && context->bodySize() != total_size) { |
123 | 0 | throw EnvoyException( |
124 | 0 | fmt::format("RpcResult is no value, but the rest of the body size({}) not equal 0", |
125 | 0 | (context->bodySize() - total_size))); |
126 | 0 | } |
127 | | |
128 | 0 | return {result, true}; |
129 | 0 | } |
130 | | |
131 | | size_t DubboHessian2SerializerImpl::serializeRpcResult(Buffer::Instance& output_buffer, |
132 | | const std::string& content, |
133 | 0 | RpcResponseType type) { |
134 | 0 | size_t origin_length = output_buffer.length(); |
135 | 0 | Hessian2::Encoder encoder(std::make_unique<BufferWriter>(output_buffer)); |
136 | | |
137 | | // The serialized response type is compact int. |
138 | 0 | bool result = encoder.encode(static_cast<std::underlying_type<RpcResponseType>::type>(type)); |
139 | 0 | result |= encoder.encode(content); |
140 | |
|
141 | 0 | ASSERT(result); |
142 | | |
143 | 0 | return output_buffer.length() - origin_length; |
144 | 0 | } |
145 | | |
146 | | class DubboHessian2SerializerConfigFactory |
147 | | : public SerializerFactoryBase<DubboHessian2SerializerImpl> { |
148 | | public: |
149 | | DubboHessian2SerializerConfigFactory() |
150 | 4 | : SerializerFactoryBase(ProtocolType::Dubbo, SerializationType::Hessian2) {} |
151 | | }; |
152 | | |
153 | | /** |
154 | | * Static registration for the Hessian protocol. @see RegisterFactory. |
155 | | */ |
156 | | REGISTER_FACTORY(DubboHessian2SerializerConfigFactory, NamedSerializerConfigFactory); |
157 | | |
158 | | } // namespace DubboProxy |
159 | | } // namespace NetworkFilters |
160 | | } // namespace Extensions |
161 | | } // namespace Envoy |