#include "websocket_v8_bindings.h" #include "websocket_bridge.h" #include using namespace v8; void v8_runt_websocket_server_create(const FunctionCallbackInfo& 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& 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& 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& 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& 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 buffer = args[1].As(); void* data = buffer->GetBackingStore()->Data(); size_t length = buffer->ByteLength(); runt_websocket_server_send_all_binary(serverId, static_cast(data), length); } else if (args[1]->IsArrayBufferView()) { Local view = args[1].As(); Local buffer = view->Buffer(); void* data = static_cast(buffer->GetBackingStore()->Data()) + view->ByteOffset(); size_t length = view->ByteLength(); runt_websocket_server_send_all_binary(serverId, static_cast(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& 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& args) { // websocket_run_benchmark(); //} //#endif void v8_runt_websocket_server_send_client(const FunctionCallbackInfo& 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 buffer = args[2].As(); void* data = buffer->GetBackingStore()->Data(); size_t length = buffer->ByteLength(); runt_websocket_server_send_client_binary(serverId, clientId, static_cast(data), length); } else if (args[2]->IsArrayBufferView()) { Local view = args[2].As(); Local buffer = view->Buffer(); void* data = static_cast(buffer->GetBackingStore()->Data()) + view->ByteOffset(); size_t length = view->ByteLength(); runt_websocket_server_send_client_binary(serverId, clientId, static_cast(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) { // TODO: thread locking Locker locker{isolate}; Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); Local current_context = Local::New(isolate, context); Context::Scope context_scope(current_context); Local global = current_context->Global(); Local runt_obj; Local 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 }