• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
2 #include "bindingdata.h"
3 #include <base_object-inl.h>
4 #include <env-inl.h>
5 #include <memory_tracker-inl.h>
6 #include <nghttp3/nghttp3.h>
7 #include <ngtcp2/ngtcp2.h>
8 #include <node.h>
9 #include <node_errors.h>
10 #include <node_external_reference.h>
11 #include <node_mem-inl.h>
12 #include <node_realm-inl.h>
13 #include <v8.h>
14 
15 namespace node {
16 
17 using v8::Function;
18 using v8::FunctionCallbackInfo;
19 using v8::FunctionTemplate;
20 using v8::Local;
21 using v8::Object;
22 using v8::String;
23 using v8::Value;
24 
25 namespace quic {
26 
Get(Environment * env)27 BindingData& BindingData::Get(Environment* env) {
28   return *Realm::GetBindingData<BindingData>(env->context());
29 }
30 
operator ngtcp2_mem()31 BindingData::operator ngtcp2_mem() {
32   return MakeAllocator();
33 }
34 
operator nghttp3_mem()35 BindingData::operator nghttp3_mem() {
36   ngtcp2_mem allocator = *this;
37   nghttp3_mem http3_allocator = {
38       allocator.user_data,
39       allocator.malloc,
40       allocator.free,
41       allocator.calloc,
42       allocator.realloc,
43   };
44   return http3_allocator;
45 }
46 
CheckAllocatedSize(size_t previous_size) const47 void BindingData::CheckAllocatedSize(size_t previous_size) const {
48   CHECK_GE(current_ngtcp2_memory_, previous_size);
49 }
50 
IncreaseAllocatedSize(size_t size)51 void BindingData::IncreaseAllocatedSize(size_t size) {
52   current_ngtcp2_memory_ += size;
53 }
54 
DecreaseAllocatedSize(size_t size)55 void BindingData::DecreaseAllocatedSize(size_t size) {
56   current_ngtcp2_memory_ -= size;
57 }
58 
Initialize(Environment * env,Local<Object> target)59 void BindingData::Initialize(Environment* env, Local<Object> target) {
60   SetMethod(env->context(), target, "setCallbacks", SetCallbacks);
61   SetMethod(env->context(), target, "flushPacketFreelist", FlushPacketFreelist);
62   Realm::GetCurrent(env->context())
63       ->AddBindingData<BindingData>(env->context(), target);
64 }
65 
RegisterExternalReferences(ExternalReferenceRegistry * registry)66 void BindingData::RegisterExternalReferences(
67     ExternalReferenceRegistry* registry) {
68   registry->Register(SetCallbacks);
69   registry->Register(FlushPacketFreelist);
70 }
71 
BindingData(Realm * realm,Local<Object> object)72 BindingData::BindingData(Realm* realm, Local<Object> object)
73     : BaseObject(realm, object) {
74   MakeWeak();
75 }
76 
MemoryInfo(MemoryTracker * tracker) const77 void BindingData::MemoryInfo(MemoryTracker* tracker) const {
78 #define V(name, _) tracker->TrackField(#name, name##_callback());
79 
80   QUIC_JS_CALLBACKS(V)
81 
82 #undef V
83 
84 #define V(name, _) tracker->TrackField(#name, name##_string());
85 
86   QUIC_STRINGS(V)
87 
88 #undef V
89 }
90 
91 #define V(name)                                                                \
92   void BindingData::set_##name##_constructor_template(                         \
93       Local<FunctionTemplate> tmpl) {                                          \
94     name##_constructor_template_.Reset(env()->isolate(), tmpl);                \
95   }                                                                            \
96   Local<FunctionTemplate> BindingData::name##_constructor_template() const {   \
97     return PersistentToLocal::Default(env()->isolate(),                        \
98                                       name##_constructor_template_);           \
99   }
100 
101 QUIC_CONSTRUCTORS(V)
102 
103 #undef V
104 
105 #define V(name, _)                                                             \
106   void BindingData::set_##name##_callback(Local<Function> fn) {                \
107     name##_callback_.Reset(env()->isolate(), fn);                              \
108   }                                                                            \
109   Local<Function> BindingData::name##_callback() const {                       \
110     return PersistentToLocal::Default(env()->isolate(), name##_callback_);     \
111   }
112 
QUIC_JS_CALLBACKS(V)113 QUIC_JS_CALLBACKS(V)
114 
115 #undef V
116 
117 #define V(name, value)                                                         \
118   Local<String> BindingData::name##_string() const {                           \
119     if (name##_string_.IsEmpty())                                              \
120       name##_string_.Set(env()->isolate(),                                     \
121                          OneByteString(env()->isolate(), value));              \
122     return name##_string_.Get(env()->isolate());                               \
123   }
124 
125 QUIC_STRINGS(V)
126 
127 #undef V
128 
129 #define V(name, value)                                                         \
130   Local<String> BindingData::on_##name##_string() const {                      \
131     if (on_##name##_string_.IsEmpty())                                         \
132       on_##name##_string_.Set(                                                 \
133           env()->isolate(),                                                    \
134           FIXED_ONE_BYTE_STRING(env()->isolate(), "on" #value));               \
135     return on_##name##_string_.Get(env()->isolate());                          \
136   }
137 
138 QUIC_JS_CALLBACKS(V)
139 
140 #undef V
141 
142 void BindingData::SetCallbacks(const FunctionCallbackInfo<Value>& args) {
143   auto env = Environment::GetCurrent(args);
144   auto isolate = env->isolate();
145   auto& state = BindingData::Get(env);
146   CHECK(args[0]->IsObject());
147   Local<Object> obj = args[0].As<Object>();
148 
149 #define V(name, key)                                                           \
150   do {                                                                         \
151     Local<Value> val;                                                          \
152     if (!obj->Get(env->context(), state.on_##name##_string()).ToLocal(&val) || \
153         !val->IsFunction()) {                                                  \
154       return THROW_ERR_MISSING_ARGS(isolate, "Missing Callback: on" #key);     \
155     }                                                                          \
156     state.set_##name##_callback(val.As<Function>());                           \
157   } while (0);
158 
159   QUIC_JS_CALLBACKS(V)
160 
161 #undef V
162 }
163 
FlushPacketFreelist(const FunctionCallbackInfo<Value> & args)164 void BindingData::FlushPacketFreelist(const FunctionCallbackInfo<Value>& args) {
165   auto env = Environment::GetCurrent(args);
166   auto& state = BindingData::Get(env);
167   state.packet_freelist.clear();
168 }
169 
NgTcp2CallbackScope(Environment * env)170 NgTcp2CallbackScope::NgTcp2CallbackScope(Environment* env) : env(env) {
171   auto& binding = BindingData::Get(env);
172   CHECK(!binding.in_ngtcp2_callback_scope);
173   binding.in_ngtcp2_callback_scope = true;
174 }
175 
~NgTcp2CallbackScope()176 NgTcp2CallbackScope::~NgTcp2CallbackScope() {
177   auto& binding = BindingData::Get(env);
178   binding.in_ngtcp2_callback_scope = false;
179 }
180 
in_ngtcp2_callback(Environment * env)181 bool NgTcp2CallbackScope::in_ngtcp2_callback(Environment* env) {
182   auto& binding = BindingData::Get(env);
183   return binding.in_ngtcp2_callback_scope;
184 }
185 
NgHttp3CallbackScope(Environment * env)186 NgHttp3CallbackScope::NgHttp3CallbackScope(Environment* env) : env(env) {
187   auto& binding = BindingData::Get(env);
188   CHECK(!binding.in_nghttp3_callback_scope);
189   binding.in_nghttp3_callback_scope = true;
190 }
191 
~NgHttp3CallbackScope()192 NgHttp3CallbackScope::~NgHttp3CallbackScope() {
193   auto& binding = BindingData::Get(env);
194   binding.in_nghttp3_callback_scope = false;
195 }
196 
in_nghttp3_callback(Environment * env)197 bool NgHttp3CallbackScope::in_nghttp3_callback(Environment* env) {
198   auto& binding = BindingData::Get(env);
199   return binding.in_nghttp3_callback_scope;
200 }
201 
IllegalConstructor(const FunctionCallbackInfo<Value> & args)202 void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
203   THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
204 }
205 
206 }  // namespace quic
207 }  // namespace node
208 
209 #endif  // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
210