1
#include "source/extensions/matching/input_matchers/dynamic_modules/config.h"
2

            
3
#include "source/common/common/assert.h"
4
#include "source/common/config/utility.h"
5
#include "source/common/protobuf/utility.h"
6
#include "source/extensions/dynamic_modules/dynamic_modules.h"
7

            
8
namespace Envoy {
9
namespace Extensions {
10
namespace Matching {
11
namespace InputMatchers {
12
namespace DynamicModules {
13

            
14
::Envoy::Matcher::InputMatcherFactoryCb
15
DynamicModuleInputMatcherFactory::createInputMatcherFactoryCb(
16
10
    const Protobuf::Message& config, Server::Configuration::ServerFactoryContext& /*context*/) {
17
10
  ASSERT_IS_MAIN_OR_TEST_THREAD();
18

            
19
10
  const auto& proto_config = dynamic_cast<const envoy::extensions::matching::input_matchers::
20
10
                                              dynamic_modules::v3::DynamicModuleMatcher&>(config);
21

            
22
10
  const auto& module_config = proto_config.dynamic_module_config();
23
10
  auto dynamic_module_or_error = Extensions::DynamicModules::newDynamicModuleByName(
24
10
      module_config.name(), module_config.do_not_close(), module_config.load_globally());
25

            
26
10
  if (!dynamic_module_or_error.ok()) {
27
1
    throw EnvoyException("Failed to load dynamic module: " +
28
1
                         std::string(dynamic_module_or_error.status().message()));
29
1
  }
30

            
31
9
  auto dynamic_module = std::move(dynamic_module_or_error.value());
32

            
33
  // Resolve required symbols.
34
9
  auto on_config_new = dynamic_module->getFunctionPointer<OnMatcherConfigNewType>(
35
9
      "envoy_dynamic_module_on_matcher_config_new");
36
9
  if (!on_config_new.ok()) {
37
1
    throw EnvoyException("Failed to resolve symbol: " +
38
1
                         std::string(on_config_new.status().message()));
39
1
  }
40

            
41
8
  auto on_config_destroy = dynamic_module->getFunctionPointer<OnMatcherConfigDestroyType>(
42
8
      "envoy_dynamic_module_on_matcher_config_destroy");
43
8
  if (!on_config_destroy.ok()) {
44
1
    throw EnvoyException("Failed to resolve symbol: " +
45
1
                         std::string(on_config_destroy.status().message()));
46
1
  }
47

            
48
7
  auto on_match = dynamic_module->getFunctionPointer<OnMatcherMatchType>(
49
7
      "envoy_dynamic_module_on_matcher_match");
50
7
  if (!on_match.ok()) {
51
1
    throw EnvoyException("Failed to resolve symbol: " + std::string(on_match.status().message()));
52
1
  }
53

            
54
  // Parse the matcher config.
55
6
  std::string matcher_config_str;
56
6
  if (proto_config.has_matcher_config()) {
57
4
    auto config_or_error = MessageUtil::knownAnyToBytes(proto_config.matcher_config());
58
4
    if (!config_or_error.ok()) {
59
      throw EnvoyException("Failed to parse matcher config: " +
60
                           std::string(config_or_error.status().message()));
61
    }
62
4
    matcher_config_str = std::move(config_or_error.value());
63
4
  }
64

            
65
  // Create the in-module configuration.
66
6
  envoy_dynamic_module_type_envoy_buffer name_buf = {.ptr = proto_config.matcher_name().data(),
67
6
                                                     .length = proto_config.matcher_name().size()};
68
6
  envoy_dynamic_module_type_envoy_buffer config_buf = {.ptr = matcher_config_str.data(),
69
6
                                                       .length = matcher_config_str.size()};
70

            
71
6
  auto in_module_config = (*on_config_new.value())(nullptr, name_buf, config_buf);
72
6
  if (in_module_config == nullptr) {
73
1
    throw EnvoyException("Failed to initialize dynamic module matcher config");
74
1
  }
75

            
76
  // Capture everything needed for the factory callback. The module is shared so it stays loaded.
77
5
  auto shared_module =
78
5
      std::shared_ptr<Extensions::DynamicModules::DynamicModule>(std::move(dynamic_module));
79

            
80
5
  return [shared_module, on_config_destroy = on_config_destroy.value(), on_match = on_match.value(),
81
5
          in_module_config] {
82
5
    return std::make_unique<DynamicModuleInputMatcher>(shared_module, on_config_destroy, on_match,
83
5
                                                       in_module_config);
84
5
  };
85
6
}
86

            
87
REGISTER_FACTORY(DynamicModuleInputMatcherFactory, ::Envoy::Matcher::InputMatcherFactory);
88

            
89
} // namespace DynamicModules
90
} // namespace InputMatchers
91
} // namespace Matching
92
} // namespace Extensions
93
} // namespace Envoy