Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/extensions/common/wasm/wasm.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <atomic>
4
#include <chrono>
5
#include <map>
6
#include <memory>
7
8
#include "envoy/common/exception.h"
9
#include "envoy/extensions/wasm/v3/wasm.pb.validate.h"
10
#include "envoy/http/filter.h"
11
#include "envoy/server/lifecycle_notifier.h"
12
#include "envoy/stats/scope.h"
13
#include "envoy/stats/stats.h"
14
#include "envoy/thread_local/thread_local_object.h"
15
#include "envoy/upstream/cluster_manager.h"
16
17
#include "source/common/common/assert.h"
18
#include "source/common/common/logger.h"
19
#include "source/common/config/datasource.h"
20
#include "source/common/stats/symbol_table.h"
21
#include "source/common/version/version.h"
22
#include "source/extensions/common/wasm/context.h"
23
#include "source/extensions/common/wasm/plugin.h"
24
#include "source/extensions/common/wasm/remote_async_datasource.h"
25
#include "source/extensions/common/wasm/stats_handler.h"
26
#include "source/extensions/common/wasm/wasm_vm.h"
27
28
#include "include/proxy-wasm/exports.h"
29
#include "include/proxy-wasm/wasm.h"
30
31
namespace Envoy {
32
namespace Extensions {
33
namespace Common {
34
namespace Wasm {
35
36
using CreateContextFn =
37
    std::function<ContextBase*(Wasm* wasm, const std::shared_ptr<Plugin>& plugin)>;
38
39
class WasmHandle;
40
41
// Wasm execution instance. Manages the Envoy side of the Wasm interface.
42
class Wasm : public WasmBase, Logger::Loggable<Logger::Id::wasm> {
43
public:
44
  Wasm(WasmConfig& config, absl::string_view vm_key, const Stats::ScopeSharedPtr& scope,
45
       Api::Api& api, Upstream::ClusterManager& cluster_manager, Event::Dispatcher& dispatcher);
46
  Wasm(std::shared_ptr<WasmHandle> other, Event::Dispatcher& dispatcher);
47
  ~Wasm() override;
48
49
0
  Upstream::ClusterManager& clusterManager() const { return cluster_manager_; }
50
0
  Event::Dispatcher& dispatcher() { return dispatcher_; }
51
0
  Api::Api& api() { return api_; }
52
0
  Context* getRootContext(const std::shared_ptr<PluginBase>& plugin, bool allow_closed) {
53
0
    return static_cast<Context*>(WasmBase::getRootContext(plugin, allow_closed));
54
0
  }
55
  void setTimerPeriod(uint32_t root_context_id, std::chrono::milliseconds period) override;
56
  virtual void tickHandler(uint32_t root_context_id);
57
0
  std::shared_ptr<Wasm> sharedThis() { return std::static_pointer_cast<Wasm>(shared_from_this()); }
58
0
  Network::DnsResolverSharedPtr& dnsResolver() { return dns_resolver_; }
59
60
  // WasmBase
61
  void error(std::string_view message) override;
62
  proxy_wasm::CallOnThreadFunction callOnThreadFunction() override;
63
  ContextBase* createContext(const std::shared_ptr<PluginBase>& plugin) override;
64
  ContextBase* createRootContext(const std::shared_ptr<PluginBase>& plugin) override;
65
  ContextBase* createVmContext() override;
66
  void registerCallbacks() override;
67
  void getFunctions() override;
68
69
  // AccessLog::Instance
70
  void log(const PluginSharedPtr& plugin, const Formatter::HttpFormatterContext& log_context,
71
           const StreamInfo::StreamInfo& info);
72
73
  void onStatsUpdate(const PluginSharedPtr& plugin, Envoy::Stats::MetricSnapshot& snapshot);
74
75
0
  virtual std::string buildVersion() { return BUILD_VERSION_NUMBER; }
76
77
  void initializeLifecycle(Server::ServerLifecycleNotifier& lifecycle_notifier);
78
0
  uint32_t nextDnsToken() {
79
0
    do {
80
0
      dns_token_++;
81
0
    } while (!dns_token_);
82
0
    return dns_token_;
83
0
  }
84
85
  void setCreateContextForTesting(CreateContextFn create_context,
86
0
                                  CreateContextFn create_root_context) {
87
0
    create_context_for_testing_ = create_context;
88
0
    create_root_context_for_testing_ = create_root_context;
89
0
  }
90
0
  void setFailStateForTesting(proxy_wasm::FailState fail_state) { failed_ = fail_state; }
91
92
protected:
93
  friend class Context;
94
95
  void initializeStats();
96
  // Calls into the VM.
97
  proxy_wasm::WasmCallVoid<3> on_resolve_dns_;
98
  proxy_wasm::WasmCallVoid<2> on_stats_update_;
99
100
  Stats::ScopeSharedPtr scope_;
101
  Api::Api& api_;
102
  Stats::StatNamePool stat_name_pool_;
103
  const Stats::StatName custom_stat_namespace_;
104
  Upstream::ClusterManager& cluster_manager_;
105
  Event::Dispatcher& dispatcher_;
106
  Event::PostCb server_shutdown_post_cb_;
107
  absl::flat_hash_map<uint32_t, Event::TimerPtr> timer_; // per root_id.
108
  TimeSource& time_source_;
109
110
  // Lifecycle stats
111
  LifecycleStatsHandler lifecycle_stats_handler_;
112
113
  // Plugin stats
114
  absl::flat_hash_map<uint32_t, Stats::Counter*> counters_;
115
  absl::flat_hash_map<uint32_t, Stats::Gauge*> gauges_;
116
  absl::flat_hash_map<uint32_t, Stats::Histogram*> histograms_;
117
118
  CreateContextFn create_context_for_testing_;
119
  CreateContextFn create_root_context_for_testing_;
120
  Network::DnsResolverSharedPtr dns_resolver_;
121
  uint32_t dns_token_ = 1;
122
};
123
using WasmSharedPtr = std::shared_ptr<Wasm>;
124
125
class WasmHandle : public WasmHandleBase, public ThreadLocal::ThreadLocalObject {
126
public:
127
  explicit WasmHandle(const WasmSharedPtr& wasm)
128
1
      : WasmHandleBase(std::static_pointer_cast<WasmBase>(wasm)), wasm_(wasm) {}
129
130
0
  WasmSharedPtr& wasm() { return wasm_; }
131
132
private:
133
  WasmSharedPtr wasm_;
134
};
135
136
using WasmHandleSharedPtr = std::shared_ptr<WasmHandle>;
137
138
class PluginHandle : public PluginHandleBase {
139
public:
140
  explicit PluginHandle(const WasmHandleSharedPtr& wasm_handle, const PluginSharedPtr& plugin)
141
      : PluginHandleBase(std::static_pointer_cast<WasmHandleBase>(wasm_handle),
142
                         std::static_pointer_cast<PluginBase>(plugin)),
143
11
        plugin_(plugin), wasm_handle_(wasm_handle) {}
144
145
0
  WasmHandleSharedPtr& wasmHandle() { return wasm_handle_; }
146
0
  uint32_t rootContextId() { return wasm_handle_->wasm()->getRootContext(plugin_, false)->id(); }
147
148
private:
149
  PluginSharedPtr plugin_;
150
  WasmHandleSharedPtr wasm_handle_;
151
};
152
153
using PluginHandleSharedPtr = std::shared_ptr<PluginHandle>;
154
155
class PluginHandleSharedPtrThreadLocal : public ThreadLocal::ThreadLocalObject {
156
public:
157
11
  PluginHandleSharedPtrThreadLocal(PluginHandleSharedPtr handle) : handle_(handle){};
158
0
  PluginHandleSharedPtr& handle() { return handle_; }
159
160
private:
161
  PluginHandleSharedPtr handle_;
162
};
163
164
using CreateWasmCallback = std::function<void(WasmHandleSharedPtr)>;
165
166
// Returns false if createWasm failed synchronously. This is necessary because xDS *MUST* report
167
// all failures synchronously as it has no facility to report configuration update failures
168
// asynchronously. Callers should throw an exception if they are part of a synchronous xDS update
169
// because that is the mechanism for reporting configuration errors.
170
bool createWasm(const PluginSharedPtr& plugin, const Stats::ScopeSharedPtr& scope,
171
                Upstream::ClusterManager& cluster_manager, Init::Manager& init_manager,
172
                Event::Dispatcher& dispatcher, Api::Api& api,
173
                Envoy::Server::ServerLifecycleNotifier& lifecycle_notifier,
174
                RemoteAsyncDataProviderPtr& remote_data_provider, CreateWasmCallback&& callback,
175
                CreateContextFn create_root_context_for_testing = nullptr);
176
177
PluginHandleSharedPtr
178
getOrCreateThreadLocalPlugin(const WasmHandleSharedPtr& base_wasm, const PluginSharedPtr& plugin,
179
                             Event::Dispatcher& dispatcher,
180
                             CreateContextFn create_root_context_for_testing = nullptr);
181
182
void clearCodeCacheForTesting();
183
void setTimeOffsetForCodeCacheForTesting(MonotonicTime::duration d);
184
WasmEvent toWasmEvent(const std::shared_ptr<WasmHandleBase>& wasm);
185
186
} // namespace Wasm
187
} // namespace Common
188
} // namespace Extensions
189
} // namespace Envoy