Skip to content

Commit

Permalink
feat: add bindSync and unbindSync for the sockets
Browse files Browse the repository at this point in the history
  • Loading branch information
aminya committed Dec 30, 2024
1 parent d473c10 commit a399b5b
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 85 deletions.
14 changes: 0 additions & 14 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,20 +166,6 @@ jobs:
run: rm -rf ./tmp
shell: bash

- name: Test Compatibility
if: ${{ !matrix.dockerfile }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 5
max_attempts: 2
command: |
pnpm run test.unit.compat
continue-on-error: true

- name: Clean Tmp
run: rm -rf ./tmp
shell: bash

- name: Test Electron Windows/MacOS
if: "${{ !contains(matrix.os, 'ubuntu') && !matrix.dockerfile }}"
uses: nick-fields/retry@v3
Expand Down
2 changes: 1 addition & 1 deletion .mocharc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const config = {
"expose-gc": true,
"v8-expose-gc": true,
exit: true,
parallel: false,
parallel: true,
timeout: 6000,
retries: 3,
fullTrace: true,
Expand Down
11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"devDependencies": {
"@types/benchmark": "~2.1.5",
"@types/chai": "^4",
"@types/deasync": "~0.1.5",
"@types/eslint": "~9.6.1",
"@types/fs-extra": "^11.0.4",
"@types/gh-pages": "~6.1.0",
Expand All @@ -38,7 +37,6 @@
"benchmark": "^2.1.4",
"chai": "^4",
"cross-env": "^7.0.3",
"deasync": "^0.1.30",
"downlevel-dts": "^0.11.0",
"electron": "^33.2.1",
"electron-mocha": "^13.0.1",
Expand Down Expand Up @@ -105,12 +103,11 @@
"build.debug": "run-s build.js build.native.debug",
"test": "run-s test.unit",
"test.debug": "run-s test.unit.debug",
"test.unit": "run-s clean.temp build && mocha ./test/unit/*-test.ts",
"test.unit.debug": "run-s clean.temp build.debug && mocha ./test/unit/*-test.ts",
"test.unit.compat": "run-s clean.temp build && cross-env INCLUDE_COMPAT_TESTS=true mocha ./test/unit/compat/*-test.ts",
"test.unit": "run-s clean.temp build && cross-env INCLUDE_COMPAT_TESTS=true mocha ./test/unit/*-test.ts ./test/unit/compat/*-test.ts",
"test.unit.debug": "run-s clean.temp build.debug && cross-env INCLUDE_COMPAT_TESTS=true mocha ./test/unit/*-test.ts ./test/unit/compat/*-test.ts",
"test.unit.nogc": "run-s clean.temp build && cross-env SKIP_GC_TESTS=true mocha",
"test.electron.main": "run-s clean.temp build && cross-env SKIP_GC_TESTS=true electron-mocha ./test/unit/*-test.ts",
"test.electron.renderer": "run-s build && electron-mocha --renderer ./test/unit/*-test.ts",
"test.electron.main": "run-s clean.temp build && cross-env INCLUDE_COMPAT_TESTS=true SKIP_GC_TESTS=true electron-mocha ./test/unit/*-test.ts ./test/unit/compat/*-test.ts",
"test.electron.renderer": "run-s build && cross-env INCLUDE_COMPAT_TESTS=true SKIP_GC_TESTS=true electron-mocha --renderer ./test/unit/*-test.ts ./test/unit/compat/*-test.ts",
"test.smoke": "bash ./script/smoke-test.bash",
"format": "run-s format.prettier format.clang-format",
"format.prettier": "prettier -l --cache --cache-location ./.cache/prettier --write .",
Expand Down
37 changes: 0 additions & 37 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 4 additions & 26 deletions src/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,34 +327,12 @@ class Socket extends EventEmitter {
)
}

bindSync(...args: Parameters<Socket["bind"]>) {
try {
Object.defineProperty(this, "bindSync", {
value: require("deasync")(this.bind),
})
} catch (err) {
throw new Error(
"bindSync() has been removed from compatibility mode; " +
"use bind() instead, or add 'deasync' to your project dependencies",
)
}

this.bindSync(...args)
bindSync(address: string) {
this._socket.bindSync(address)
}

unbindSync(...args: Parameters<Socket["unbind"]>) {
try {
Object.defineProperty(this, "unbindSync", {
value: require("deasync")(this.unbind),
})
} catch (err) {
throw new Error(
"unbindSync() has been removed from compatibility mode; " +
"use unbind() instead, or add 'deasync' to your project dependencies",
)
}

this.unbindSync(...args)
unbindSync(address: string) {
this._socket.unbindSync(address)
}

pause() {
Expand Down
30 changes: 30 additions & 0 deletions src/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,26 @@ export declare abstract class Socket {
*/
bind(address: string): Promise<void>

/**
* Binds the socket to the given address. During {@link bind}() the socket
* cannot be used. Do not call any other methods until the returned promise
* resolves. Make sure to use `await`.
*
* You can use `*` in place of a hostname to bind on all interfaces/addresses,
* and you can use `*` in place of a port to bind to a random port (which can
* be retrieved with {@link lastEndpoint} later).
*
* ```typescript
* socket.bindSync("tcp://127.0.0.1:3456")
* socket.bindSync("tcp://*:3456") // binds on all interfaces
* socket.bindSync("tcp://127.0.0.1:*") // binds on random port
* ```
*
* @param address Address to bind this socket to.
* @returns Resolved when the socket was successfully bound.
*/
bindSync(address: string): void

/**
* Unbinds the socket to the given address. During {@link unbind}() the socket
* cannot be used. Do not call any other methods until the returned promise
Expand All @@ -549,6 +569,16 @@ export declare abstract class Socket {
*/
unbind(address: string): Promise<void>

/**
* Unbinds the socket to the given address. During {@link unbind}() the socket
* cannot be used. Do not call any other methods until the returned promise
* resolves. Make sure to use `await`.
*
* @param address Address to unbind this socket from.
* @returns Resolved when the socket was successfully unbound.
* */
unbindSync(address: string): void

/**
* Connects to the socket at the given remote address and returns immediately.
* The connection will be made asynchronously in the background.
Expand Down
80 changes: 80 additions & 0 deletions src/socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,44 @@ Napi::Value Socket::Bind(const Napi::CallbackInfo& info) {
return res.Promise();
}

Napi::Value Socket::BindSync(const Napi::CallbackInfo& info) {
Arg::Validator const args{
Arg::Required<Arg::String>("Address must be a string"),
};

if (args.ThrowIfInvalid(info)) {
return Env().Undefined();
}

if (!ValidateOpen()) {
return Env().Undefined();
}

state = Socket::State::Blocked;
auto run_ctx = std::make_shared<AddressContext>(info[0].As<Napi::String>());

while (zmq_bind(socket, run_ctx->address.c_str()) < 0) {
if (zmq_errno() != EINTR) {
run_ctx->error = static_cast<uint32_t>(zmq_errno());
break;
}
}

state = Socket::State::Open;
endpoints++;

if (request_close) {
Close();
}

if (run_ctx->error != 0) {
ErrnoException(Env(), static_cast<int32_t>(run_ctx->error), run_ctx->address)
.ThrowAsJavaScriptException();
}

return Env().Undefined();
}

Napi::Value Socket::Unbind(const Napi::CallbackInfo& info) {
Arg::Validator const args{
Arg::Required<Arg::String>("Address must be a string"),
Expand Down Expand Up @@ -463,6 +501,44 @@ Napi::Value Socket::Unbind(const Napi::CallbackInfo& info) {
return res.Promise();
}

Napi::Value Socket::UnbindSync(const Napi::CallbackInfo& info) {
Arg::Validator const args{
Arg::Required<Arg::String>("Address must be a string"),
};

if (args.ThrowIfInvalid(info)) {
return Env().Undefined();
}

if (!ValidateOpen()) {
return Env().Undefined();
}

state = Socket::State::Blocked;
auto run_ctx = std::make_shared<AddressContext>(info[0].As<Napi::String>());

while (zmq_unbind(socket, run_ctx->address.c_str()) < 0) {
if (zmq_errno() != EINTR) {
run_ctx->error = static_cast<uint32_t>(zmq_errno());
break;
}
}

state = Socket::State::Open;
--endpoints;

if (request_close) {
Close();
}

if (run_ctx->error != 0) {
ErrnoException(Env(), static_cast<int32_t>(run_ctx->error), run_ctx->address)
.ThrowAsJavaScriptException();
}

return Env().Undefined();
}

void Socket::Connect(const Napi::CallbackInfo& info) {
Arg::Validator const args{
Arg::Required<Arg::String>("Address must be a string"),
Expand Down Expand Up @@ -919,6 +995,10 @@ void Socket::Initialize(Module& module, Napi::Object& exports) {
auto proto = {
InstanceMethod<&Socket::Bind>("bind"),
InstanceMethod<&Socket::Unbind>("unbind"),

InstanceMethod<&Socket::BindSync>("bindSync"),
InstanceMethod<&Socket::BindSync>("unbindSync"),

InstanceMethod<&Socket::Connect>("connect"),
InstanceMethod<&Socket::Disconnect>("disconnect"),
InstanceMethod<&Socket::Close>("close"),
Expand Down
3 changes: 3 additions & 0 deletions src/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class Socket : public Napi::ObjectWrap<Socket>, public Closable {
inline void Close(const Napi::CallbackInfo& info);

inline Napi::Value Bind(const Napi::CallbackInfo& info);
inline Napi::Value BindSync(const Napi::CallbackInfo& info);

inline Napi::Value Unbind(const Napi::CallbackInfo& info);
inline Napi::Value UnbindSync(const Napi::CallbackInfo& info);

inline void Connect(const Napi::CallbackInfo& info);
inline void Disconnect(const Napi::CallbackInfo& info);
Expand Down

0 comments on commit a399b5b

Please sign in to comment.