Skip to content

Accept() closes the listener socket on success — a listener can only accept one connection #79

Description

@cdgraff

Summary

NodeSRT::Accept() (in src/node-srt.cc) calls srt_close() on the listener socket on the success path, so the listening socket is destroyed after every accepted connection. This makes it impossible to accept more than one connection from a single listener without re-creating it.

Details

Napi::Value NodeSRT::Accept(const Napi::CallbackInfo& info) {
  ...
  int their_fd = srt_accept(socketValue, (struct sockaddr *)&their_addr, &addr_size);
  if (their_fd == SRT_INVALID_SOCK) {
    srt_close(socketValue);      // failure path
    ...
    return Napi::Number::New(env, SRT_ERROR);
  }
  srt_close(socketValue);        // <-- success path: closes the LISTENER
  socketValue = Napi::Number::New(env, SRT_INVALID_SOCK);
  return Napi::Number::New(env, their_fd);
}

In libsrt, srt_accept() returns the newly accepted socket and leaves the listener open so it can keep accepting. Closing the listener here diverges from that contract.

Impact

  • A server can accept only one connection per listener; after the first accept() the listener goes to SRT_SOCKSTATUS BROKEN and subsequent callers time out.
  • To work around it, apps must re-create (bind+listen) the listener after every accept. That drops the listener's backlog of pending handshakes, so when several callers connect at nearly the same time, only one is accepted and the rest fail with an I/O error (their handshakes are lost when the listener is destroyed). This is very visible under a burst of simultaneous connections (e.g. after a restart), where the large majority of callers fail to connect.

Reproduction

  1. Create a listener (createSocketbindlistenepollAddUsock).
  2. Connect one caller; call accept(listenerFd).
  3. Check getSockState(listenerFd) immediately after: it is BROKEN (6), then NONEXIST (9). Any further caller times out.

With the success-path srt_close removed, the listener stays LISTENING (3) and accepts multiple connections normally (verified: 1/3 → 3/3 sequential callers; and a burst of N simultaneous callers goes from ~1/N to N/N).

Suggested fix

Remove the srt_close(socketValue) (and the following no-op reassignment) on the success path, so Accept() only returns the accepted fd and leaves the listener open — matching libsrt semantics. The caller is responsible for closing the listener when done.

Happy to open a PR if that helps.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready-for-maintainerReviewed by triage bot; awaiting human merge

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions