Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add callback to the websocket send function #307

Open
jwoodrow opened this issue Sep 13, 2020 · 0 comments
Open

add callback to the websocket send function #307

jwoodrow opened this issue Sep 13, 2020 · 0 comments

Comments

@jwoodrow
Copy link

jwoodrow commented Sep 13, 2020

In the original websocket implementation there is an optional callback that can be passed on to the WebSocket.prototype.send function.

https://github.com/websockets/ws/blob/master/doc/ws.md#websocketsenddata-options-callback

I do not know how complicated it would be to add this to the current implementation of mock-socket but I'm willing to try my hand at it if someone could give me better insight into where this should be done because I'm currently using the callbacks in my project to turn send into a Promise.

I've tried to dig deep into the ws implementation of send and the furthest I could get was here

function createWriteWrap(handle, callback) {
  const req = new WriteWrap();

  req.handle = handle;
  req.oncomplete = onWriteComplete;
  req.async = false;
  req.bytes = 0;
  req.buffer = null;
  req.callback = callback;

  return req;
}
send(data, options, cb) {
  const buf = toBuffer(data);
  const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
  let opcode = options.binary ? 2 : 1;
  let rsv1 = options.compress;

  if (this._firstFragment) {
    this._firstFragment = false;
    if (rsv1 && perMessageDeflate) {
      rsv1 = buf.length >= perMessageDeflate._threshold;
    }
    this._compress = rsv1;
  } else {
    rsv1 = false;
    opcode = 0;
  }

  if (options.fin) this._firstFragment = true;

  if (perMessageDeflate) {
    const opts = {
      fin: options.fin,
      rsv1,
      opcode,
      mask: options.mask,
      readOnly: toBuffer.readOnly
    };

    if (this._deflating) {
      this.enqueue([this.dispatch, buf, this._compress, opts, cb]);
    } else {
      this.dispatch(buf, this._compress, opts, cb);
    }
  } else {
    this.sendFrame(
      Sender.frame(buf, {
        fin: options.fin,
        rsv1: false,
        opcode,
        mask: options.mask,
        readOnly: toBuffer.readOnly
      }),
      cb
    );
  }
}
sendFrame(list, cb) {
  if (list.length === 2) {
    this._socket.cork();
    this._socket.write(list[0]);
    this._socket.write(list[1], cb);
    this._socket.uncork();
  } else {
    this._socket.write(list[0], cb);
  }
}
Socket.prototype._write = function(data, encoding, cb) {
  this._writeGeneric(false, data, encoding, cb);
};
Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
  // If we are still connecting, then buffer this for later.
  // The Writable logic will buffer up any more writes while
  // waiting for this one to be done.
  if (this.connecting) {
    this._pendingData = data;
    this._pendingEncoding = encoding;
    this.once('connect', function connect() {
      this._writeGeneric(writev, data, encoding, cb);
    });
    return;
  }
  this._pendingData = null;
  this._pendingEncoding = '';

  if (!this._handle) {
    cb(new ERR_SOCKET_CLOSED());
    return false;
  }

  this._unrefTimer();

  let req;
  if (writev)
    req = writevGeneric(this, data, cb);
  else
    req = writeGeneric(this, data, encoding, cb);
  if (req.async)
    this[kLastWriteQueueSize] = req.bytes;
};
function writeGeneric(self, data, encoding, cb) {
  const req = createWriteWrap(self[kHandle], cb);
  const err = handleWriteReq(req, data, encoding);

  afterWriteDispatched(req, err, cb);
  return req;
}
function createWriteWrap(handle, callback) {
  const req = new WriteWrap();

  req.handle = handle;
  req.oncomplete = onWriteComplete;
  req.async = false;
  req.bytes = 0;
  req.buffer = null;
  req.callback = callback;

  return req;
}

After that it appears to go into C territory. I think I went a bit overboard with the digging though. I'm sure there's probably a simple implementation of the send callback to be able to mock it correctly I might be able to submit as a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant