231 lines
12 KiB
C++
231 lines
12 KiB
C++
#include "websocket_v8_bindings.h"
|
|
#include "websocket_bridge.h"
|
|
#include <kinc/log.h>
|
|
|
|
using namespace v8;
|
|
|
|
void v8_runt_websocket_server_create(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 3 || !args[0]->IsString() || !args[1]->IsNumber() || !args[2]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_create requires (host, port, maxConnections)").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
String::Utf8Value host(isolate, args[0]);
|
|
int port = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int maxConnections = args[2]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
int serverId = runt_websocket_server_create(*host, port, maxConnections);
|
|
args.GetReturnValue().Set(Integer::New(isolate, serverId));
|
|
}
|
|
|
|
void v8_runt_websocket_server_start(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 1 || !args[0]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_start requires serverId").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
int serverId = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
bool success = runt_websocket_server_start(serverId);
|
|
args.GetReturnValue().Set(Boolean::New(isolate, success));
|
|
}
|
|
|
|
void v8_runt_websocket_server_stop(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 1 || !args[0]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_stop requires serverId").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
int serverId = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
runt_websocket_server_stop(serverId);
|
|
args.GetReturnValue().Set(Undefined(isolate));
|
|
}
|
|
|
|
void v8_runt_websocket_server_tick(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 1 || !args[0]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_tick requires serverId").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
int serverId = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
runt_websocket_server_tick(serverId);
|
|
args.GetReturnValue().Set(Undefined(isolate));
|
|
}
|
|
|
|
void v8_runt_websocket_server_send_all(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 2 || !args[0]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_send_all requires (serverId, data)").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
int serverId = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
if (args[1]->IsArrayBuffer()) {
|
|
Local<ArrayBuffer> buffer = args[1].As<ArrayBuffer>();
|
|
void* data = buffer->GetBackingStore()->Data();
|
|
size_t length = buffer->ByteLength();
|
|
runt_websocket_server_send_all_binary(serverId, static_cast<const char*>(data), length);
|
|
} else if (args[1]->IsArrayBufferView()) {
|
|
Local<ArrayBufferView> view = args[1].As<ArrayBufferView>();
|
|
Local<ArrayBuffer> buffer = view->Buffer();
|
|
void* data = static_cast<char*>(buffer->GetBackingStore()->Data()) + view->ByteOffset();
|
|
size_t length = view->ByteLength();
|
|
runt_websocket_server_send_all_binary(serverId, static_cast<const char*>(data), length);
|
|
} else if (args[1]->IsString()) {
|
|
String::Utf8Value data(isolate, args[1]);
|
|
runt_websocket_server_send_all(serverId, *data);
|
|
} else {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_send_all data must be String or ArrayBuffer").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
args.GetReturnValue().Set(Undefined(isolate));
|
|
}
|
|
|
|
//#ifdef WITH_BENCHMARK
|
|
//extern "C" {
|
|
// void websocket_run_groupchat_test(int rate, int duration);
|
|
// void websocket_run_benchmark();
|
|
//}
|
|
|
|
//void v8_websocket_run_test(const FunctionCallbackInfo<Value>& args) {
|
|
// Isolate* isolate = args.GetIsolate();
|
|
// int rate = 60, duration = 5;
|
|
// if (args.Length() >= 1 && args[0]->IsNumber()) {
|
|
// rate = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
// }
|
|
// if (args.Length() >= 2 && args[1]->IsNumber()) {
|
|
// duration = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
// }
|
|
// websocket_run_groupchat_test(rate, duration);
|
|
//}
|
|
|
|
//void v8_websocket_run_benchmark(const FunctionCallbackInfo<Value>& args) {
|
|
// websocket_run_benchmark();
|
|
//}
|
|
//#endif
|
|
|
|
void v8_runt_websocket_server_send_client(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
if (args.Length() < 3 || !args[0]->IsNumber() || !args[1]->IsNumber()) {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_send_client requires (serverId, clientId, data)").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
int serverId = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int clientId = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
if (args[2]->IsArrayBuffer()) {
|
|
Local<ArrayBuffer> buffer = args[2].As<ArrayBuffer>();
|
|
void* data = buffer->GetBackingStore()->Data();
|
|
size_t length = buffer->ByteLength();
|
|
runt_websocket_server_send_client_binary(serverId, clientId, static_cast<const char*>(data), length);
|
|
} else if (args[2]->IsArrayBufferView()) {
|
|
Local<ArrayBufferView> view = args[2].As<ArrayBufferView>();
|
|
Local<ArrayBuffer> buffer = view->Buffer();
|
|
void* data = static_cast<char*>(buffer->GetBackingStore()->Data()) + view->ByteOffset();
|
|
size_t length = view->ByteLength();
|
|
runt_websocket_server_send_client_binary(serverId, clientId, static_cast<const char*>(data), length);
|
|
} else if (args[2]->IsString()) {
|
|
String::Utf8Value data(isolate, args[2]);
|
|
runt_websocket_server_send_client(serverId, clientId, *data);
|
|
} else {
|
|
isolate->ThrowException(Exception::TypeError(
|
|
String::NewFromUtf8(isolate, "runt_websocket_server_send_client data must be String or ArrayBuffer").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
args.GetReturnValue().Set(Undefined(isolate));
|
|
}
|
|
|
|
void bind_websocket_bridge(Isolate* isolate, const Global<Context>& context) {
|
|
// TODO: thread locking
|
|
Locker locker{isolate};
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
|
|
Local<Context> current_context = Local<Context>::New(isolate, context);
|
|
Context::Scope context_scope(current_context);
|
|
Local<Object> global = current_context->Global();
|
|
|
|
Local<Object> runt_obj;
|
|
Local<Value> existing_runt = global->Get(current_context, String::NewFromUtf8(isolate, "RunT").ToLocalChecked()).ToLocalChecked();
|
|
if (existing_runt->IsObject()) {
|
|
runt_obj = existing_runt->ToObject(current_context).ToLocalChecked();
|
|
} else {
|
|
runt_obj = Object::New(isolate);
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "RunT").ToLocalChecked(), runt_obj);
|
|
}
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerCreate").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_create).ToLocalChecked());
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerStart").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_start).ToLocalChecked());
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerStop").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_stop).ToLocalChecked());
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerTick").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_tick).ToLocalChecked());
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerSendAll").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_send_all).ToLocalChecked());
|
|
|
|
runt_obj->Set(current_context, String::NewFromUtf8(isolate, "websocketServerSendClient").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_send_client).ToLocalChecked());
|
|
|
|
// uWS compatibility aliases
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerCreate").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_create).ToLocalChecked());
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerDestroy").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_stop).ToLocalChecked());
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerSend").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_send_all).ToLocalChecked());
|
|
// runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerTick").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_tick).ToLocalChecked());
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerSetOnConnection").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_start).ToLocalChecked());
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerSetOnMessage").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_start).ToLocalChecked());
|
|
//runt_obj->Set(current_context, String::NewFromUtf8(isolate, "uwsWebsocketServerSetOnDisconnection").ToLocalChecked(),
|
|
// Function::New(current_context, v8_runt_websocket_server_stop).ToLocalChecked());
|
|
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_create").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_create).ToLocalChecked());
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_start").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_start).ToLocalChecked());
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_stop").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_stop).ToLocalChecked());
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_tick").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_tick).ToLocalChecked());
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_send_all").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_send_all).ToLocalChecked());
|
|
global->Set(current_context, String::NewFromUtf8(isolate, "runt_websocket_server_send_client").ToLocalChecked(),
|
|
Function::New(current_context, v8_runt_websocket_server_send_client).ToLocalChecked());
|
|
|
|
//#ifdef WITH_BENCHMARK
|
|
// global->Set(current_context, String::NewFromUtf8(isolate, "websocket_run_test").ToLocalChecked(),
|
|
// Function::New(current_context, v8_websocket_run_test).ToLocalChecked());
|
|
// global->Set(current_context, String::NewFromUtf8(isolate, "websocket_run_benchmark").ToLocalChecked(),
|
|
// Function::New(current_context, v8_websocket_run_benchmark).ToLocalChecked());
|
|
//#endif
|
|
}
|