--- /dev/null
+#KEASRC = /tmp/kea/src/lib
+
+# Kea includes and boost
+CPPFLAGS = -I../../.. -I$(KEASRC) -I/usr/local/include
+# v8
+
+CXXFLAGS = -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_DEPRECATED
+CXXFLAGS += -g -fPIC -dynamic -DNDEBUG -fwrapv
+# v8
+CXXFLAGS += -Wno-c++11-extensions
+
+# Kea dhcp library
+LIBS = -lkea-dhcp++ -lkea-hooks -lkea-exceptions
+# v8
+LIBS += -lv8_base -lv8_libbase -lv8_snapshot -lv8_libplatform -lv8
+
+# Kea dependencies
+LDFLAGS = -L/usr/local/Cellar/botan/1.10.12/lib
+LDFLAGS += -L$(KEASRC)/dhcp/.libs
+LDFLAGS += -L$(KEASRC)/hooks/.libs
+LDFLAGS += -L$(KEASRC)/exceptions/.libs
+# v8
+
+SRCS = dso.cc globals.cc globals.h voption.h voption.cc vpkt4.h vpkt4.cc
+
+OBJS = dso.o globals.o voption.o vpkt4.o
+
+all: kea.so tests
+
+kea.so: $(OBJS)
+ g++ -shared $(OBJS) $(LDFLAGS) $(LIBS) -o kea.so
+
+TESTLIBS = -lkea-dhcpsrv -lkea-dhcp++ -lkea-asiolink -lkea-cc
+TESTLIBS += -lkea-hooks -lkea-log -lkea-exceptions
+
+TESTLDFLAGS = -L/usr/local/Cellar/botan/1.10.12/lib
+TESTLDFLAGS += -L$(KEASRC)/dhcpsrv/.libs
+TESTLDFLAGS += -L$(KEASRC)/dhcp/.libs
+TESTLDFLAGS += -L$(KEASRC)/asiolink/.libs
+TESTLDFLAGS += -L$(KEASRC)/cc/.libs
+TESTLDFLAGS += -L$(KEASRC)/hooks/.libs
+TESTLDFLAGS += -L$(KEASRC)/log/.libs
+TESTLDFLAGS += -L$(KEASRC)/exceptions/.libs
+
+tests: tests.o
+ g++ tests.o $(TESTLDFLAGS) $(TESTLIBS) -o tests
+
+clean:
+ rm -f *.o *.so tests
Context::Scope context_scope(context);
// Initialize option and pkt4
- init_option_template(isolate_);
- init_pkt4_template(isolate_);
+ init_option(isolate_);
+ init_pkt4(isolate_);
// Import script file content
Local<String> source =
Context::Scope context_scope(context);
// Create pkt4 object
- Local<ObjectTemplate> templ =
- Local<ObjectTemplate>::New(isolate_, pkt4_template);
- Local<Object> query;
- if (!templ->NewInstance(context).ToLocal(&query)) {
- String::Utf8Value error(try_catch.Exception());
- cerr << "NewInstance failed: " << *error << "\n";
+ Local<Object> query = make_pkt4(isolate_, query4);
+ if (query.IsEmpty()) {
+ cerr << "empty v8 query\n";
return (0);
}
- v8_pkt4* ccpobj(new v8_pkt4());
- ccpobj->object = query4;
- Local<External> ptr = External::New(isolate_, ccpobj);
- query->SetInternalField(0, ptr);
// Call the handler
const int argc = 1;
Local<Value> result;
if (!handler->Call(context, context->Global(),
argc, argv).ToLocal(&result)) {
- cerr << "call failed\n";
String::Utf8Value error(try_catch.Exception());
cerr << "pkt4_receive handler failed: " << *error << "\n";
return (0);
// finalize (how to call it?)
void
-option_finalize(Local<Object> obj) {
+option_finalize(const WeakCallbackData<Object, v8_option>& data) {
// This is a critical code to avoid memory leaks
cout << "option_finalize called\n";
- Local<External> field = Local<External>::Cast(obj->GetInternalField(0));
+ Local<External> field =
+ Local<External>::Cast(data.GetValue()->GetInternalField(0));
+ delete static_cast<v8_option*>(field->Value());
+}
+
+// toString
+void
+option_tostring(const FunctionCallbackInfo<Value>& info) {
+ HandleScope handle_scope(info.GetIsolate());
+
+ Local<External> field =
+ Local<External>::Cast(info.Holder()->GetInternalField(0));
v8_option* const self = static_cast<v8_option*>(field->Value());
- self->object.reset();
- delete self;
+ info.GetReturnValue().Set(
+ String::NewFromUtf8(info.GetIsolate(),
+ self->object->toText().c_str(),
+ NewStringType::kNormal).ToLocalChecked());
}
} // end of anonymous namespace
Global<ObjectTemplate> option_template;
-void init_option_template(Isolate* isolate) {
+Local<Object> make_option(Isolate* isolate, OptionPtr opt) {
+ // Create a stack-allocated handle scope.
+ EscapableHandleScope handle_scope(isolate);
+
+ // Catch errors
+ TryCatch try_catch(isolate);
+
+ // Generate a new instance from the template
+ Local<ObjectTemplate> templ =
+ Local<ObjectTemplate>::New(isolate, option_template);
+ Local<Object> result;
+ if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&result)) {
+ String::Utf8Value error(try_catch.Exception());
+ cerr << "NewInstance failed: " << *error << "\n";
+ return (handle_scope.Escape(result));
+ }
+
+ // Set the C++ part
+ v8_option* ccpobj(new v8_option());
+ ccpobj->object = opt;
+ Local<External> ptr = External::New(isolate, ccpobj);
+ result->SetInternalField(0, ptr);
+
+ // Show the new value to the garbage collector
+ Persistent<Object> gcref(isolate, result);
+ gcref.SetWeak<v8_option>(ccpobj, option_finalize);
+
+ return (handle_scope.Escape(result));
+}
+
+void init_option(Isolate* isolate) {
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
// Get one field
templ->SetInternalFieldCount(1);
- ///// TODO set methods
+ // Set Methods
+ Local<Function> tostring;
+ if (!Function::New(isolate->GetCurrentContext(),
+ option_tostring).ToLocal(&tostring)) {
+ cerr << "can't create pkt4_tostring\n";
+ }
+ templ->Set(isolate, "toString", tostring);
// Store it
option_template.Reset(isolate, templ);
// Ocaml option class
class v8_option {
+public:
v8_option();
-public:
isc::dhcp::OptionPtr object;
};
-extern ::v8::Global< ::v8::ObjectTemplate> option_template;
+::v8::Local< ::v8::Object> make_option(::v8::Isolate* isolate,
+ isc::dhcp::OptionPtr opt);
-void init_option_template(::v8::Isolate* isolate);
+void init_option(::v8::Isolate* isolate);
} // end of namespace v8
} // end of namespace isc
// finalize (how to call it?)
void
-pkt4_finalize(Local<Object> obj) {
+pkt4_finalize(const WeakCallbackData<Object, v8_pkt4>& data) {
// This is a critical code to avoid memory leaks
cout << "pkt4_finalize called\n";
- Local<External> field = Local<External>::Cast(obj->GetInternalField(0));
- v8_pkt4* const self = static_cast<v8_pkt4*>(field->Value());
- self->object.reset();
- delete self;
+ Local<External> field =
+ Local<External>::Cast(data.GetValue()->GetInternalField(0));
+ delete static_cast<v8_pkt4*>(field->Value());
}
// toString
Global<ObjectTemplate> pkt4_template;
-void init_pkt4_template(Isolate* isolate) {
+Local<Object> make_pkt4(Isolate* isolate, Pkt4Ptr pkt) {
+ // Create a stack-allocated handle scope.
+ EscapableHandleScope handle_scope(isolate);
+
+ // Catch errors
+ TryCatch try_catch(isolate);
+
+ // Generate a new instance from the template
+ Local<ObjectTemplate> templ =
+ Local<ObjectTemplate>::New(isolate, pkt4_template);
+ Local<Object> result;
+ if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&result)) {
+ String::Utf8Value error(try_catch.Exception());
+ cerr << "NewInstance failed: " << *error << "\n";
+ return (handle_scope.Escape(result));
+ }
+
+ // Set the C++ part
+ v8_pkt4* ccpobj(new v8_pkt4());
+ ccpobj->object = pkt;
+ Local<External> ptr = External::New(isolate, ccpobj);
+ result->SetInternalField(0, ptr);
+
+ // Show the new value to the garbage collector
+ Persistent<Object> gcref(isolate, result);
+ gcref.SetWeak<v8_pkt4>(ccpobj, pkt4_finalize);
+
+ return (handle_scope.Escape(result));
+}
+
+void init_pkt4(Isolate* isolate) {
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
isc::dhcp::Pkt4Ptr object;
};
-extern ::v8::Global< ::v8::ObjectTemplate> pkt4_template;
+::v8::Local< ::v8::Object> make_pkt4(::v8::Isolate* isolate,
+ isc::dhcp::Pkt4Ptr pkt);
-void init_pkt4_template(::v8::Isolate* isolate);
+void init_pkt4(::v8::Isolate* isolate);
} // end of namespace v8
} // end of namespace isc