Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setsockopt under node.js?

Is there a setsockopt/getsockopt-like socket options manipulation functionality in node.js?

like image 682
Nikolai Gorchilov Avatar asked Dec 26 '22 15:12

Nikolai Gorchilov


1 Answers

I'm expanding on the comment left by socketpair which shows getsockopt. You can accomplish this by using ffi and ref. I've reformatted this to allow it to be easily manipulated.

I edited my comment because I had to make some changes to make the code work on both Linux and Win32. I had to create a node library for Windows to get the socket handle and pass it to setsockopt. Be aware that Linux and Windows may have different values for socket options

Edit: Here's a cleaned up piece of of production code I'm using:

var net = require("net");
var ffi = require("ffi");
var ref = require("ref");
var getSocketHandleAddress;

var SOL_SOCKET = 0x1;
var SO_OOBINLINE = 0xA;
var _setsockopt;

if (process.platform == "win32") {
  SOL_SOCKET = 0xffff;
  SO_OOBINLINE = 0x0100;
}

var setSocketOption = function (handle, level, option, value) {
  if (!_setsockopt) {
    var library;
    var paramTypes;
    if (process.platform === "win32") {
      library = "ws2_32.dll";
      paramTypes = [
        ref.types.int,
        ref.types.int,
        ref.types.int,
        ref.refType(ref.types.void),
        ref.types.int
      ];
    } else {
      paramTypes = [
        ref.types.int,
        ref.types.int,
        ref.types.int,
        ref.refType(ref.types.void),
        ref.refType(ref.types.int)
      ];
    }
    var lib = new ffi.DynamicLibrary(library);
    _setsockopt = ffi.ForeignFunction(
      lib.get("setsockopt"),
      ref.types.int,
      paramTypes);
  }
  var refType;
  var length;
  if (typeof value === "boolean") {
    refType = ref.types.bool;
  } else {
    refType = ref.types.int;
  }
  if (process.platform !== "win32") {
    return _setsockopt(
      handle.fd, 
      level, 
      option, 
      ref.alloc(refType, value), 
      ref.alloc(ref.types.int, refType.size)
    );
  }
  if (!getSocketHandleAddress) {
    getSocketHandleAddress = require("getsockethandleaddress");
  }
  return _setsockopt(
    getSocketHandleAddress.getAddress(handle),
    level,
    option,
    ref.alloc(refType, value), 
    refType.size
  );

};

var tcpserver = net.createServer(function (socket) {
  var ret = setSocketOption(socket._handle, SOL_SOCKET, SO_OOBINLINE, true);
  if (ret !== 0) {
    console.error("OOB Inline socket option failed: " + ret);
  }
});
like image 104
ShortFuse Avatar answered Jan 06 '23 20:01

ShortFuse