uWebSockets.js/src/WebSocketWrapper.h

113 lines
4.4 KiB
C
Raw Normal View History

2019-01-14 10:45:25 +00:00
#include "App.h"
#include <v8.h>
#include "Utilities.h"
using namespace v8;
2019-01-18 15:57:54 +00:00
/* todo: probably isCorked, cork should be exposed? */
2019-01-14 10:54:37 +00:00
struct WebSocketWrapper {
static Persistent<Object> wsTemplate[2];
2019-01-14 10:34:20 +00:00
2019-01-14 11:16:24 +00:00
template <bool SSL>
static inline uWS::WebSocket<SSL, true> *getWebSocket(const FunctionCallbackInfo<Value> &args) {
2019-01-18 15:57:54 +00:00
auto *ws = (uWS::WebSocket<SSL, true> *) args.Holder()->GetAlignedPointerFromInternalField(0);
if (!ws) {
args.GetReturnValue().Set(isolate->ThrowException(String::NewFromUtf8(isolate, "Invalid access of closed uWS.WebSocket/SSLWebSocket.")));
}
return ws;
}
static inline void invalidateWsObject(const FunctionCallbackInfo<Value> &args) {
args.Holder()->SetAlignedPointerInInternalField(0, nullptr);
2019-01-14 11:16:24 +00:00
}
/* It would make sense to call terminate "close" and call close "end" to line up with HTTP */
/* That also makes sense seince close takes message and code -> you can end with a string message */
/* Takes nothing returns nothing */
template <bool SSL>
static void uWS_WebSocket_terminate(const FunctionCallbackInfo<Value> &args) {
auto *ws = getWebSocket<SSL>(args);
if (ws) {
invalidateWsObject(args);
ws->terminate();
}
}
2019-01-14 11:16:24 +00:00
/* Takes code, message, returns undefined */
template <bool SSL>
static void uWS_WebSocket_close(const FunctionCallbackInfo<Value> &args) {
2019-01-18 15:57:54 +00:00
auto *ws = getWebSocket<SSL>(args);
if (ws) {
int code = 0;
if (args.Length() >= 1) {
code = args[0]->Uint32Value();
}
2019-01-14 11:16:24 +00:00
2019-01-18 15:57:54 +00:00
NativeString message(args.GetIsolate(), args[1]);
if (message.isInvalid(args)) {
return;
}
2019-01-14 11:16:24 +00:00
2019-01-18 15:57:54 +00:00
invalidateWsObject(args);
ws->close(code, message.getString());
}
2019-01-14 11:16:24 +00:00
}
2019-01-14 10:34:20 +00:00
2019-01-14 11:16:24 +00:00
/* Takes nothing, returns integer */
template <bool SSL>
static void uWS_WebSocket_getBufferedAmount(const FunctionCallbackInfo<Value> &args) {
2019-01-18 15:57:54 +00:00
auto *ws = getWebSocket<SSL>(args);
if (ws) {
int bufferedAmount = ws->getBufferedAmount();
args.GetReturnValue().Set(Integer::New(isolate, bufferedAmount));
}
2019-01-14 11:16:24 +00:00
}
/* Takes message, isBinary. Returns true on success, false otherwise */
2019-01-14 10:54:37 +00:00
template <bool SSL>
static void uWS_WebSocket_send(const FunctionCallbackInfo<Value> &args) {
2019-01-18 15:57:54 +00:00
auto *ws = getWebSocket<SSL>(args);
if (ws) {
NativeString message(args.GetIsolate(), args[0]);
if (message.isInvalid(args)) {
return;
}
2019-01-14 10:34:20 +00:00
2019-01-18 15:57:54 +00:00
bool ok = ws->send(message.getString(), args[1]->BooleanValue() ? uWS::OpCode::BINARY : uWS::OpCode::TEXT);
2019-01-14 10:34:20 +00:00
2019-01-18 15:57:54 +00:00
args.GetReturnValue().Set(Boolean::New(isolate, ok));
}
2019-01-14 10:54:37 +00:00
}
2019-01-14 10:34:20 +00:00
2019-01-14 10:54:37 +00:00
template <bool SSL>
static void initWsTemplate() {
Local<FunctionTemplate> wsTemplateLocal = FunctionTemplate::New(isolate);
if (SSL) {
wsTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.SSLWebSocket"));
} else {
wsTemplateLocal->SetClassName(String::NewFromUtf8(isolate, "uWS.WebSocket"));
}
wsTemplateLocal->InstanceTemplate()->SetInternalFieldCount(1);
2019-01-14 11:16:24 +00:00
/* Register our functions */
2019-01-14 10:54:37 +00:00
wsTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "send"), FunctionTemplate::New(isolate, uWS_WebSocket_send<SSL>));
2019-01-14 11:16:24 +00:00
wsTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "close"), FunctionTemplate::New(isolate, uWS_WebSocket_close<SSL>));
wsTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "terminate"), FunctionTemplate::New(isolate, uWS_WebSocket_terminate<SSL>));
2019-01-14 11:16:24 +00:00
wsTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getBufferedAmount"), FunctionTemplate::New(isolate, uWS_WebSocket_getBufferedAmount<SSL>));
2019-01-14 10:54:37 +00:00
2019-01-14 11:16:24 +00:00
/* Create the template */
2019-01-14 10:54:37 +00:00
Local<Object> wsObjectLocal = wsTemplateLocal->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
wsTemplate[SSL].Reset(isolate, wsObjectLocal);
2019-01-14 10:34:20 +00:00
}
2019-01-14 11:16:24 +00:00
/* This is where we output an instance */
2019-01-14 10:54:37 +00:00
template <class APP>
static Local<Object> getWsInstance() {
return Local<Object>::New(isolate, wsTemplate[std::is_same<APP, uWS::SSLApp>::value])->Clone();
}
};
2019-01-14 10:34:20 +00:00
2019-01-14 11:16:24 +00:00
/* Fix this, should be nicer */
2019-01-14 10:54:37 +00:00
Persistent<Object> WebSocketWrapper::wsTemplate[2];