Coverage Report

Created: 2023-11-12 09:30

/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