From fb10ac9b61d701c32b4af21c5a485a7a45fbc100 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Wed, 26 Dec 2018 15:23:14 +0100 Subject: [PATCH] Make websockets benchmarkable --- examples/HelloWorld.js | 6 +++--- src/addon.cpp | 44 ++++++++++++++++++++++++++++++++++-------- uWebSockets | 2 +- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/examples/HelloWorld.js b/examples/HelloWorld.js index c0d201d..f13e3a0 100644 --- a/examples/HelloWorld.js +++ b/examples/HelloWorld.js @@ -11,10 +11,10 @@ const app = uWS./*SSL*/App({ res.end('Hejdå!'); }).ws('/*', { open: (ws, req) => { - console.log('hello websocket!'); + console.log(ws); }, - message: () => { - console.log('message from websocket yo'); + message: (ws, message) => { + ws.send(message); } }).listen(port, (token) => { if (token) { diff --git a/src/addon.cpp b/src/addon.cpp index fa3a701..e570c7a 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -21,6 +21,7 @@ using namespace v8; Isolate *isolate; Persistent resTemplate; Persistent reqTemplate; +Persistent wsTemplate; #include #include @@ -101,8 +102,15 @@ void req_getHeader(const FunctionCallbackInfo &args) { } /* WebSocket send */ -void uWS_WebSocket_send() { +// not properly templated, just like the httpsockets are not! +void uWS_WebSocket_send(const FunctionCallbackInfo &args) { + uWS::WebSocket *ws = (uWS::WebSocket *) args.Holder()->GetAlignedPointerFromInternalField(0); + NativeString nativeString(args.GetIsolate(), args[0]); + + //std::cout << std::string_view(nativeString.getData(), nativeString.getLength()) << std::endl; + + ws->send(std::string_view(nativeString.getData(), nativeString.getLength()), uWS::OpCode::TEXT); } /* uWS.App.ws('/pattern', options) */ @@ -115,6 +123,10 @@ void uWS_App_ws(const FunctionCallbackInfo &args) { Persistent *openPf = new Persistent(); Persistent *messagePf = new Persistent(); + struct PerSocketData { + Persistent *socketPf; + }; + /* Get the behavior object */ if (args.Length() == 2) { Local behaviorObject = Local::Cast(args[1]); @@ -125,24 +137,31 @@ void uWS_App_ws(const FunctionCallbackInfo &args) { messagePf->Reset(args.GetIsolate(), Local::Cast(behaviorObject->Get(String::NewFromUtf8(isolate, "message")))); } - app->template ws(std::string(nativeString.getData(), nativeString.getLength()), { + app->template ws(std::string(nativeString.getData(), nativeString.getLength()), { /*.compression = uWS::SHARED_COMPRESSOR, .maxPayloadLength = 16 * 1024,*/ .open = [openPf](auto *ws, auto *req) { HandleScope hs(isolate); + /* Create a new websocket object */ + Local wsObject = Local::New(isolate, wsTemplate)->Clone(); + wsObject->SetAlignedPointerInInternalField(0, ws); + /* Attach a new V8 object with pointer to us, to us */ + PerSocketData *perSocketData = (PerSocketData *) ws->getUserData(); + perSocketData->socketPf = new Persistent; + perSocketData->socketPf->Reset(isolate, wsObject); - //Local argv[] = {resObject, reqObject}; - Local::New(isolate, *openPf)->Call(isolate->GetCurrentContext()->Global(), 0, nullptr); - + Local argv[] = {wsObject}; + Local::New(isolate, *openPf)->Call(isolate->GetCurrentContext()->Global(), 1, argv); }, .message = [messagePf](auto *ws, std::string_view message, uWS::OpCode opCode) { HandleScope hs(isolate); - /* ws's user data holds pointer to persistent object which is the V8 representation we pass here */ - Local argv[] = {}; // ws, message, opCode - Local::New(isolate, *messagePf)->Call(isolate->GetCurrentContext()->Global(), 1, argv); + + PerSocketData *perSocketData = (PerSocketData *) ws->getUserData(); + Local argv[2] = {Local::New(isolate, *(perSocketData->socketPf)), ArrayBuffer::New(isolate, (void *) message.data(), message.length())}; // ws, message, opCode + Local::New(isolate, *messagePf)->Call(isolate->GetCurrentContext()->Global(), 2, argv); }/* .drain = []() {}, .ping = []() {}, @@ -301,6 +320,15 @@ void Main(Local exports) { exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App)->GetFunction()); exports->Set(String::NewFromUtf8(isolate, "nextTick"), FunctionTemplate::New(isolate, nextTick)->GetFunction()); + /* The template for websockets */ + Local wsTemplateLocal = FunctionTemplate::New(isolate); + wsTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.WebSocket")); + wsTemplateLocal->InstanceTemplate()->SetInternalFieldCount(1); + wsTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "send"), FunctionTemplate::New(isolate, uWS_WebSocket_send)); + + Local wsObjectLocal = wsTemplateLocal->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked(); + wsTemplate.Reset(isolate, wsObjectLocal); + // HttpResponse template (not templated) Local resTemplateLocal = FunctionTemplate::New(isolate); resTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.HttpResponse")); diff --git a/uWebSockets b/uWebSockets index fb95aba..c0af883 160000 --- a/uWebSockets +++ b/uWebSockets @@ -1 +1 @@ -Subproject commit fb95abad7180a22f8f2a07c627f9bd3daf97c7a5 +Subproject commit c0af883bf9517670d7b729b23baeb5346766ed45