Coverage Report

Created: 2023-11-12 09:30

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