diff --git a/lib/index.d.ts b/lib/index.d.ts index 17a655e..4be3aa3 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -238,6 +238,10 @@ export interface WebSocketConfiguration { } export class WebSocket implements Channel { constructor(config?: WebSocketConfiguration); + open(url: string): void; + forceClose(): void; + remoteAddress(): string | undefined; + path(): string | undefined; // Channel implementation close(): void; diff --git a/package-lock.json b/package-lock.json index ed87e0b..75eb6b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-datachannel", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-datachannel", - "version": "0.6.0", + "version": "0.7.1", "hasInstallScript": true, "license": "MPL 2.0", "dependencies": { diff --git a/package.json b/package.json index f364cc1..15476d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-datachannel", - "version": "0.7.0", + "version": "0.7.1", "description": "libdatachannel node bindings", "type": "module", "exports": { diff --git a/src/web-socket-wrapper.cpp b/src/web-socket-wrapper.cpp index 28fd2d1..e30018c 100644 --- a/src/web-socket-wrapper.cpp +++ b/src/web-socket-wrapper.cpp @@ -31,6 +31,7 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("open", &WebSocketWrapper::open), InstanceMethod("close", &WebSocketWrapper::close), + InstanceMethod("forceClose", &WebSocketWrapper::forceClose), InstanceMethod("sendMessage", &WebSocketWrapper::sendMessage), InstanceMethod("sendMessageBinary", &WebSocketWrapper::sendMessageBinary), InstanceMethod("isOpen", &WebSocketWrapper::isOpen), @@ -42,6 +43,8 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports) InstanceMethod("onError", &WebSocketWrapper::onError), InstanceMethod("onBufferedAmountLow", &WebSocketWrapper::onBufferedAmountLow), InstanceMethod("onMessage", &WebSocketWrapper::onMessage), + InstanceMethod("remoteAddress", &WebSocketWrapper::remoteAddress), + InstanceMethod("path", &WebSocketWrapper::path), }); constructor = Napi::Persistent(func); @@ -257,7 +260,31 @@ void WebSocketWrapper::doClose() } catch (std::exception &ex) { - std::cerr << std::string("libWebSocket error while closing WebSocket: ") + ex.what() << std::endl; + std::cerr << std::string("libdatachannel error while closing WebSocket: ") + ex.what() << std::endl; + return; + } + } + + mOnOpenCallback.reset(); + mOnErrorCallback.reset(); + mOnBufferedAmountLowCallback.reset(); + mOnMessageCallback.reset(); +} + +void WebSocketWrapper::doForceClose() +{ + PLOG_DEBUG << "doForceClose() called"; + if (mWebSocketPtr) + { + PLOG_DEBUG << "Force closing..."; + try + { + mWebSocketPtr->forceClose(); + mWebSocketPtr.reset(); + } + catch (std::exception &ex) + { + std::cerr << std::string("libdatachannel error while force closing WebSocket: ") + ex.what() << std::endl; return; } } @@ -297,7 +324,7 @@ void WebSocketWrapper::open(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException(); return; } } @@ -308,6 +335,12 @@ void WebSocketWrapper::close(const Napi::CallbackInfo &info) doClose(); } +void WebSocketWrapper::forceClose(const Napi::CallbackInfo &info) +{ + PLOG_DEBUG << "forceClose() called"; + doForceClose(); +} + Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info) { PLOG_DEBUG << "sendMessage() called"; @@ -333,7 +366,7 @@ Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException(); return Napi::Boolean::New(info.Env(), false); } } @@ -363,7 +396,7 @@ Napi::Value WebSocketWrapper::sendMessageBinary(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException(); return Napi::Boolean::New(info.Env(), false); } } @@ -384,7 +417,7 @@ Napi::Value WebSocketWrapper::isOpen(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); return Napi::Boolean::New(info.Env(), false); } } @@ -405,7 +438,7 @@ Napi::Value WebSocketWrapper::bufferedAmount(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); return Napi::Number::New(info.Env(), 0); } } @@ -426,11 +459,69 @@ Napi::Value WebSocketWrapper::maxMessageSize(const Napi::CallbackInfo &info) } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); return Napi::Number::New(info.Env(), 0); } } +Napi::Value WebSocketWrapper::remoteAddress(const Napi::CallbackInfo &info) +{ + PLOG_DEBUG << "remoteAddress() called"; + Napi::Env env = info.Env(); + + if (!mWebSocketPtr) + { + return env.Undefined(); + } + + try + { + auto address = mWebSocketPtr->remoteAddress(); + if (address.has_value()) + { + return Napi::String::New(info.Env(), address.value()); + } + else + { + return env.Undefined(); + } + } + catch (std::exception &ex) + { + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); + return env.Undefined(); + } +} + +Napi::Value WebSocketWrapper::path(const Napi::CallbackInfo &info) +{ + PLOG_DEBUG << "path() called"; + Napi::Env env = info.Env(); + + if (!mWebSocketPtr) + { + return env.Undefined(); + } + + try + { + auto path = mWebSocketPtr->path(); + if (path.has_value()) + { + return Napi::String::New(info.Env(), path.value()); + } + else + { + return env.Undefined(); + } + } + catch (std::exception &ex) + { + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); + return env.Undefined(); + } +} + void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info) { PLOG_DEBUG << "setBufferedAmountLowThreshold() called"; @@ -455,7 +546,7 @@ void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &i } catch (std::exception &ex) { - Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException(); + Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException(); return; } } diff --git a/src/web-socket-wrapper.h b/src/web-socket-wrapper.h index a5890e0..a945a85 100644 --- a/src/web-socket-wrapper.h +++ b/src/web-socket-wrapper.h @@ -23,12 +23,15 @@ class WebSocketWrapper : public Napi::ObjectWrap // Functions void open(const Napi::CallbackInfo &info); void close(const Napi::CallbackInfo &info); + void forceClose(const Napi::CallbackInfo &info); Napi::Value sendMessage(const Napi::CallbackInfo &info); Napi::Value sendMessageBinary(const Napi::CallbackInfo &info); Napi::Value isOpen(const Napi::CallbackInfo &info); Napi::Value bufferedAmount(const Napi::CallbackInfo &info); Napi::Value maxMessageSize(const Napi::CallbackInfo &info); void setBufferedAmountLowThreshold(const Napi::CallbackInfo &info); + Napi::Value remoteAddress(const Napi::CallbackInfo &info); + Napi::Value path(const Napi::CallbackInfo &info); // Callbacks void onOpen(const Napi::CallbackInfo &info); @@ -47,6 +50,7 @@ class WebSocketWrapper : public Napi::ObjectWrap static std::unordered_set instances; void doClose(); + void doForceClose(); void doCleanup(); std::shared_ptr mWebSocketPtr = nullptr; diff --git a/test/websockets.js b/test/websockets.js index f08b1e1..1c982f8 100644 --- a/test/websockets.js +++ b/test/websockets.js @@ -6,7 +6,9 @@ nodeDataChannel.preload(); const webSocketServer = new nodeDataChannel.WebSocketServer({ bindAddress: '127.0.0.1', port: 1987 }); webSocketServer.onClient((serverSocket) => { - console.log('webSocketServer.onClient()'); + console.log( + 'webSocketServer.onClient() remoteAddress: ' + serverSocket.remoteAddress() + ', path: ' + serverSocket.path(), + ); serverSocket.onOpen(() => { console.log('serverSocket.onOpen()'); @@ -32,7 +34,7 @@ clientSocket.onOpen(() => { clientSocket.onMessage((message) => { console.log('clientSocket.onMessage():', message); - clientSocket.close(); + clientSocket.forceClose(); webSocketServer.stop(); });