The rampart-net module¶
Preface¶
Acknowledgment¶
The rampart-net module makes extensive use of the libevent2 library embedded in the main rampart executable as well as the OpenSSL library, imported from the rampart-crypto module.
License¶
The rampart-net module is released under the MIT license.
What does it do?¶
The rampart-net module allows the creation of network connections and servers in a manner similar to (but with significant differences from) the node.js net module.
All of the callback functions in rampart-net are asynchronously executed in rampart’s event loop unless stated otherwise.
All functions return their parent object, for chainability, unless otherwise stated.
Loading and Using the Module¶
Loading¶
                        Loading the module is a simple matter of using the require() function:
                      
var net = require("rampart-net");
                        Socket Functions¶
new net.Socket()¶
In order to make a tcp connection to a server, a new Socket object must be created. The
new net.Socket()statement returns functions to connect and communicate over tcp, with or without ssl/tls.Usage:
var net = require("rampart-net"); var socket = new net.Socket();
- Return Value:
 - An object with the below listed function.
 
socket.connect()¶
Make a new tcp connection.
Usage:
var net = require("rampart-net"); var socket = new net.Socket(); socket.connect(options[, connect_callback]); /* or */ socket.connect(port[, host][, options][, connect_callback]);Where:
port- Required. The port of the server to which a connection will be attempted.
host- The hostname or ip address of the server. Default is127.0.0.1.
connect_callbackis a callback Function` which is run after a connection is established and the “connect” event is emitted.
optionsis an Object with the following optional properties:
host- The hostname or ip address of the server. Default is127.0.0.1.port- Required. A Number. The port of the server to which a connection will be attempted.timeout- How long in milliseconds before a connection is terminated for inactivity (both read and write). Default is forever.family- A Number. Must be0(the default),4or6to specify any ip family, ipv4 only or ipv6 only respectively. May be used ifhostabove resolves to both ipv4 and ipv6 addresses to force the use of a particular one.keepalive- A Boolean. Iftrueset tcp keepalive on the connection. Packets will be transparently sent to the server to aid in keeping the connection alive (should it be necessary). See this document for more information. Default isfalse.keepAliveInitialDelay- A Number. How many seconds to wait before sending the first keepalive packet. Has no effect unlesskeepaliveabove istrue. Default is1.keepAliveInterval- A Number. How many seconds between sending keepalive packets. Has no effect unlesskeepaliveabove istrue. Default is1.keepAliveCount- A Number. How many keepalive packets should be sent with no reply before disconnecting. Has no effect unlesskeepaliveabove istrue. Default is10.tls- A Boolean. Whether to use SSL/TLS for the connection. Default isfalse.ssl- Same astls. If both set,sslis ignored.insecure- A Boolean. Whether to skip verification of the server’s credentials when making a connection over SSL/TLS. The default isfalse(i.e. check credentials and fail the connection if the server’s credentials are not verified).cacert- A String. The path to the CA certificate store file, required to verify the server when using SSL/TLS. The default is system dependent (usually/etc/ssl/cert.pemon MacOS or/etc/ssl/certs/ca-certificates.crton Linux).capath- A String. The path to the CA directory. CA certificates need to be stored as individual PEM files in this directory. No Default.hostname- A String. Name to use to verify the server if different than provided inhostabove or ifhostis a numeric ip address. No Default.
socket.write()¶
Write data to the server. The parameter can be a String or a Buffer.
var net = require("rampart-net"); var socket = new net.Socket(); function mycallback(){ // now connected, so we can write to server socket.write("hello world"); } socket.on("connect", mycallback); socket.connect(port, host);
socket.on()¶
Register a callback Function to be run when an event on
socketis emitted.Usage:
var net = require("rampart-net"); var socket = new net.Socket(); socket.on(event, callback);Where:
eventis one of the following possible events for a socket:
connect- emitted after a connection has been established.data- emitted after data has been received on the socket. The provided function takes one argument, the data received in a Buffer.ready- For compatibility. Emitted immediately after “connect”.drain- emitted when data has been written.end- emitted when disconnected by the server. Note: “close” below will also be emitted.timeout- emitted if the connection exceeds the provided timeout interval. Note: “close” below will also be emitted.close- emitted whenever a connection is terminated.error- emitted upon error. Note: if no error callback is registered for a socket, rampart will throw an error instead.
callbackis a function. Iferror, function will have its first parameter be the error object/message. Ifdata, function will have its first parameter be the received data in a Buffer.
socket.off()¶
Unregister a callback Function previously registered with
socket.on. Function must be a named function.Usage example:
var net = require("rampart-net"); var socket = new net.Socket(); function mycallback(){ ... } function finishcb(){ this.off("connect", mycallback); this.off("close", finishcb); } socket.on("connect", mycallback); ... socket.on("close", finishcb);
socket.once()¶
Same as
socket.on, except the event will be removed after being called once. This is equivalent to calling off at the beginning of a callback, except with once, the function may be anonymous (unnamed).Example:
var net = require("rampart-net"); var socket = new net.Socket(); /* with on() function mycallback(){ // 'socket' and 'this' are the same socket.off("connect", mycallback); ... } socket.on("connect", mycallback); */ /* with once */ socket.once("connect", function(){ ... });
socket.destroy()¶
Close the connection to server. The “close” event is emitted upon the actual disconnect.
socket.setTimeout()¶
Set a timeout and optional timeout event callback. This is a shortcut for setting timeout value (in milliseconds) in
socket.connectand a callback usingsocket.on("timeout", mytimeoutfunc).Usage example:
var net = require("rampart-net"); var socket = new net.Socket(); function timedout(){ console.log("connection timed out"); } socket.setTimeout(5000, timedout); // five seconds
socket.setKeepAlive()¶
Set keepalive on or off, or adjust settings at any point while the socket is connected.
Usage:
socket.setKeepAlive(enable[, initialDelay[, interval[, count]]]);Where
enableis a Boolean and the optional parameters are the same as in socket.connect().
socket.trigger()¶
Trigger functions registered with socket.on() for a named event.
Usage:
socket.trigger(event[, argument]);Where
eventis a String, the name of an event registered with socket.on(), andargumentis optionally an argument to pass to the registered callbacks for the event.Arbitarty events can be registered with socket.on(), and then called with this function.
socket.bytesWritten¶
A Number - the number of bytes written to the server for the current connection.
socket.bytesRead¶
A Number - the number of bytes read from the server for the current connection.
Other socket properties¶
The
socketObject may include these possible status properties:
connecting- Boolean. Whether the connection has been initiated, but not yet established.connected- Boolean. Whether the connection has been established.tsl- Boolean. Whether this is a secure connection.destroyed- Boolean. Whether this connection has been closed or destroyed.pending- Boolean. Whether a connection has not yet been attempted.truebeforeconnectis called and aftercloseand/orendevent.falseafter connection is established.readyState- String. “open” when connected, “opening” aftersocket.connect()is called andundefinedafter close or beforesocket.connect()is called._events- Object. Registered callbacks for events.timeout- Number. Timeout value, if set.remoteAddress- String. IP address of the connected remote peer.remotePort- Number. Port of the connected remote peer.remoteFamily- String. IP version used for connection (ipv4oripv6)._hostPort- Number. Same asremotePort_hostAddrs- Object. Host address used for this connection returned from a call to new net.Resolver() by socket.connect() internally.sslCipher- String. Iftlsis true, the name of the openssl cipher being used for this connection.
Socket Full Example¶
/* simulate a https request to google.com */
rampart.globalize(rampart.utils);
var net = require('rampart-net');
var socket = new net.Socket();
socket.on("connect", function(){
    console.log("CONNECTED");
    this.write("GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
});
socket.on("ready", function(){
    console.log("READY");
});
// http 1.0, server should disconnect us.
socket.on('end', function() {
    console.log("END EVENT");;
});
/* just to demonstrate multiple callbacks */
socket.on('data', function(data) {
    printf("\nlength=%d\n",data.length);
});
socket.on('data', function(data) {
    printf("\ncontent:\n%s\n",data);
});
socket.on('close', function() {
    printf("Close - written: %s, read: %s\n", this.bytesWritten, this.bytesRead);
});
socket.on('error', function(err) {
    console.log("ERROR:", err);
});
socket.on('timeout', function(){
    console.log("TIMEOUT")
});
socket.setTimeout(1000);
// now actually connect
socket.connect({
    host: "google.com",
    port: 443,
    tls: true
});
/* end of script, event loop started, connection made, callbacks executed */
/*
    Expected results:
        CONNECTED
        READY
        length=703
        content:
        HTTP/1.0 301 Moved Permanently
        Location: https://www.google.com/
        Content-Type: text/html; charset=UTF-8
        Date: Thu, 07 Jul 2022 06:19:02 GMT
        Expires: Sat, 06 Aug 2022 06:19:02 GMT
        Cache-Control: public, max-age=2592000
        Server: gws
        Content-Length: 220
        X-XSS-Protection: 0
        X-Frame-Options: SAMEORIGIN
        Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
        <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
        <TITLE>301 Moved</TITLE></HEAD><BODY>
        <H1>301 Moved</H1>
        The document has moved
        <A HREF="https://www.google.com/">here</A>.
        </BODY></HTML>
        END EVENT
        Close - written: 36, read: 703
*/
                        Server Functions¶
new net.Server()¶
In order to listen for tcp connections from clients, a new Server object must be created. The
new net.Server()statement returns functions to listen and create sockets to communicate over tcp, with or without ssl/tls.Usage:
var net = require("rampart-net"); var server = new net.Server([options ][,connection_callback]);Where:
optionsis an Object of options:
tls- AKAsecure- a Boolean - Whether to serve using ssl/tls. Default isfalse. Iftrue, thesslKeyFileandsslCertFileparameters must also be set.sslKeyFile: A String, the location of the ssl key file for serving over ssl/tls. An example, if using letsencrypt for “example.com” might be"/etc/letsencrypt/live/example.com/privkey.pem". This setting has no effect unlesstlsorsecureistrue.sslCertFile: A String, the location of the ssl cert file for serving over ssl/tls. An example, if using letsencrypt for “example.com” might be"/etc/letsencrypt/live/example.com/fullchain.pem". This setting has no effect unlesstlsorsecureistrue.sslMinVersion: A String, the minimum SSL/TLS version to use. Possible values aressl3,tls1,tls1.1ortls1.2. The default istls1.2. This setting has no effect unlesstlsorsecureistrue.
connection_callback- a Function - a callback executed when theconnectionevent is emitted (when the server accepts a new connection). The “connection” event calls registered functions with a single parameter (thesocketobject, representing the socket connection to the client).
- Return Value:
 - An object with the below listed function.
 
server.listen()¶
Set server to listen on the given port, and optionally ip addresses.
Usage:
var net = require("rampart-net"); var server = new net.Server([ [options ][,connection_callback]]); server.listen(port[, host[, backlog]][, listen_callback]); /* or */ server.listen(options[, listen_callback]);Where:
port- A Number. The port upon which to listen. Required.
host- A String or Array of Strings. Hosts and/or IP addresses to bind. Default is"any"If unset or set to"any", it will bind all available IPV4 and IPV6 addresses.
backlog- A Number. The maximum length of the queue of pending connections. Default is511.
listen_callback- A Function. A function to be executed when the “listening” event is emitted (when server starts listening).
options- An Object with the following properties:
port- Same as above.host- Same as above.backlog- Same as above.maxConnections- Same as server.maxConnections() below.family- A Number. Must be0(the default),4or6to specify any ip family, ipv4 only or ipv6 only respectively. May be used ifhostabove resolves to both ipv4 and ipv6 addresses to force the use of a particular one.
server.on()¶
Register a callback Function to be run when an event on
serveris emitted.Usage:
var net = require("rampart-net"); var server = new net.Server(); server.on(event, callback);Where:
eventis one of the following possible events for a socket:
connection- emitted after a new connection has been established. The callback is provided asocketobject, connected to the client.listening- emitted after server has binds to the given port and is ready to accept connection.close- emitted when the server is terminated.error- emitted upon error. Note: if no error callback is registered for the server, rampart will throw an error instead.
callbackis a function. Iferror, function will have its first parameter be the error object/message. Ifdata, function will have its first parameter be the received data in a Buffer.
server.off()¶
Unregister a callback Function previously registered withserver.on. Function must be a named function.
server.once()¶
Same asserver.on, except the event will be removed after being called once. This is equivalent to calling off at the beginning of the callback, except withonce, the function may be anonymous (unnamed). See example for socket.once().
server.connectionCount()¶
Get the number of connected clients.
- Return Value:
 - A Number, the number of connected clients.
 
server.maxConnections()¶
Set the maximum number of connections concurrently connected. The server will drop new connections if this number is reached. This function can be called at any time to set or adjust the connection limit.
Usage:
var net = require("rampart-net"); var server = new net.Server(); server.maxConnections([max]);Where
maxis a Number, the maximum allowed connections. Default is0(meaning no max) if no value is provided. Setting to a number greater than 4,294,967,295 or less than 0 is equivalent to setting0. Actual system maximum number of connections varies by platform and settings.
Other server properties¶
The
serverObject may include these possible status properties:
listening- Boolean. Whether the connection has been initiated, but not yet established._events- Object. Registered callbacks for events.tsl- Boolean. Whether server accepts secure connections.sslKeyFile- String. The SSL/TLS key file, if providedsslCertFil- String. The SSL/TLS cert file, if provided.maxConnections- Number.maxConnectionsvalue, if set._hostAddrs- Array of Objects. Host addresses that the server is listening on as returned from a call to resolver.resolve() by server.listen() internally._hostPort- Number. The port used by the server.backlog- Number.backlogvalue, if set, or the default of511.
Server Full Example¶
/* Simulate an https server, return request headers as text */ rampart.globalize(rampart.utils); var net = require('rampart-net'); var cert = "/etc/letsencrypt/live/example.com/fullchain.pem"; var key = "/etc/letsencrypt/live/example.com/privkey.pem"; var nc=0; var server = new net.Server( { "secure":true, sslKeyFile:key, sslCertFile:cert }, function(socket) { console.log("CONNECTED"); /* assuming all request data will be provided in a single callback */ socket.on('data', function(data){ var ind = bufferToString(data); printf("connection %s, open connections %s\n", ++nc, server.connectionCount()); socket.write( "HTTP/1.0 200 OK\r\n" + "Content-type: text/plain\r\n" + "Content-Length: " + ind.length + "\r\n\r\n" ); socket.write(ind); socket.destroy(); }) .on('end', function(){ console.log("peer ended connection ", this.remoteAddress); }) .on('error', console.log ) .on('close', function(){ console.log("closed connection to ", this.remoteAddress); }); } ); server.maxConnections(1200); server.on("error", function (err) { console.log("server err:",err); }) .on("close", function () { console.log("server closed"); }) .on("listening", function(){ printf("LISTENING. server properties:\n%3J\n", this); }) .listen({ port: 8888, maxConnections: 1200 }); /* Output upon Start: LISTENING. server properties: { "listening": true, "_events": { "connection": {}, "error": {}, "close": {}, "listening": {} }, "sslKeyFile": "/etc/letsencrypt/live/example.com/fullchain.pem", "sslCertFile": "/etc/letsencrypt/live/example.com/privkey.pem", "tls": true, "maxConnections": 1200, "_hostAddrs": [ { "host": "0.0.0.0", "ip4addrs": [ "0.0.0.0" ], "ip6addrs": [], "ipaddrs": [ "0.0.0.0" ], "canonName": "0.0.0.0", "ip": "0.0.0.0", "ipv4": "0.0.0.0" }, { "host": "::", "ip4addrs": [], "ip6addrs": [ "::" ], "ipaddrs": [ "::" ], "canonName": "::", "ip": "::", "ipv6": "::" } ], "_hostPort": 8888, "backlog": 511 } Request: curl https://example.com:8888/ GET / HTTP/1.1 Host: example.com:8888 User-Agent: curl/7.58.0 Accept: * /* Output after request: CONNECTED connection 1, open connections 1 closed connection to 2001:db8::1 */
Resolve functions¶
The following functions are used to resolve a host name to one or more ip addresses.
new net.Resolver()¶
Create a new resolve object.
Usage:
var net = require("rampart-net"); var resolver = new net.Resolver();
resolver.resolve()¶
Resolve a host name to ip address.
Usage:
var net = require("rampart-net"); var resolver = new net.Resolver(); resolver.resolve(host[, nameserver][, lookup_callback]);Where:
hostis a String - the host name to be resolved.nameserveris a String - the ip address of the DNS server to query (default is system specified nameservers in, e.g. /etc/resolv.conf).lookup_callbackis a Function - an optional “lookup” event callback.
- NOTE:
 
resolver.resolve()may be called multiple times at any time, however each time an anonymous function is provided as thelookup_callback, that additional callback will be run for each “lookup” event. Note that duplicate named functions are only run once per event.var net = require("rampart-net"); var resolver = new net.Resolver(); /* console.log is run once per lookup */ resolver.resolve("google.com", console.log); resolver.resolve("rampart.dev", console.log);In contrast:
var net = require("rampart-net"); var resolver = new net.Resolver(); /* console.log is run TWICE per lookup since two different * functions call it. */ resolver.resolve("google.com", function(hobj){console.log(hobj);}); resolver.resolve("rampart.dev", function(hobj){console.log(hobj);});
resolver.reverse()¶
Resolve an ip address to host name.
Usage:
var net = require("rampart-net"); var resolver = new net.Resolver(); resolver.reverse(ip_addr[, nameserver][, lookup_callback]);Where:
ip_addris a String - the ip address to look up.nameserveris a String - the ip address of the DNS server to query (default is system specified nameservers in, e.g. /etc/resolv.conf).lookup_callbackis a Function - an optional “lookup” event callback.
- NOTE:
 - See above. Note applies to
 resolver.reverse()as well.
resolver.on()¶
Register a callback function for a resolver event. Currently, the only events are
lookupanderror.Usage example:
var net = require("rampart-net"); var resolver = new net.Resolver(); resolver.on("lookup", function(hobj){ rampart.utils.printf("%3J\n", hobj); }); resolver.on("error", function(emsg){ rampart.utils.printf("Resolver error: %s\n", emsg); }); resolver.resolve("rampart.dev"); resolver.resolve("google.com"); /* probable output: { "host": "google.com", "ip4addrs": [ "142.251.214.142" ], "ip6addrs": [ "2607:f8b0:4005:80f::200e" ], "ipaddrs": [ "142.251.214.142", "2607:f8b0:4005:80f::200e" ], "ip": "142.251.214.142", "ipv4": "142.251.214.142", "ipv6": "2607:f8b0:4005:80f::200e" } { "host": "rampart.dev", "ip4addrs": [ "184.105.177.37" ], "ip6addrs": [ "2001:470:1:393::37" ], "ipaddrs": [ "184.105.177.37", "2001:470:1:393::37" ], "ip": "184.105.177.37", "ipv4": "184.105.177.37", "ipv6": "2001:470:1:393::37" } */
net.resolve()¶
Resolve a host name. This function is not asynchronous. The lookup will occur immediately, potentially before the event loop starts, and block further execution while waiting for an answer.
Usage example:
var net = require("rampart-net"); var hostobj = net.resolve("yahoo.com"); /* hostobj = { "host": "yahoo.com", "ip4addrs": [ "74.6.231.21", "98.137.11.164", "98.137.11.163", "74.6.143.26", "74.6.231.20", "74.6.143.25" ], "ip6addrs": [ "2001:4998:24:120d::1:0", "2001:4998:44:3507::8000", "2001:4998:44:3507::8001", "2001:4998:124:1507::f000", "2001:4998:24:120d::1:1", "2001:4998:124:1507::f001" ], "ipaddrs": [ "2001:4998:24:120d::1:0", "2001:4998:44:3507::8000", "2001:4998:44:3507::8001", "2001:4998:124:1507::f000", "2001:4998:24:120d::1:1", "2001:4998:124:1507::f001", "74.6.231.21", "98.137.11.164", "98.137.11.163", "74.6.143.26", "74.6.231.20", "74.6.143.25" ], "ip": "2001:4998:24:120d::1:0", "ipv6": "2001:4998:24:120d::1:0", "ipv4": "74.6.231.21" } */
net.reverse()¶
Resolve an ip address to a hostname. This function is not asynchronous. The lookup will occur immediately, potentially before the event loop starts, and wait for an answer.
Usage example:
var net = require("rampart-net"); var hostname = net.reverse("1.1.1.1"); // hostname == "one.one.one.one"
Shortcut Functions¶
net.createConnection()¶
Short cut for
new net.Socket()andsocket.connect(). AKA -net.connect().Usage:
var net = require("rampart-net"); var socket = net.createConnection(options[, connect_callback]); /* or */ var socket = net.connect(options[, connect_callback]);Where:
optionsis an Object of options, the same as found in new net.Socket() and socket.connect() above.connect_callbackis a Function, the connect callback function.This is equivalent to the following:
var net = require("rampart-net"); function netconnect(opt, cb) { var socket = new net.Socket(opt); socket.connect(opt, cb); return socket; } var socket = netconnect(options, connect_callback);Alternate usage with
port:var net = require("rampart-net"); var socket = net.createConnection(port[, host][, connect_callback]); /* or */ var socket = net.connect(port[, host][, connect_callback]);
net.createServer()¶
Short cut for
new net.Server()andserver.listen().Usage:
var net = require("rampart-net"); var server = net.createServer(options, connection_callback); /* or */ var server = net.createServer(port[, host[, backlog]][, connection_callback]);Where
optionsis an Object of options, the same as found in new net.Server() and server.listen() above.connection_callbackis a Function, the connection callback function.This is roughly equivalent to the following (when using
optionsabove):var net = require("rampart-net"); function makeserver(opt, cb) { var server = new net.Server(opt, cb); server.listen(opt); return server; } var server = makeserver(options, connect_callback);
net.resolve_async()¶
Short cut for
new net.Resolver()andresolver.resolve().Usage:
var net = require("rampart-net"); var resolver = net.resolve_async(host[, nameserver], lookup_callback);Where:
hostis a String - the host name to be resolved.nameserveris a String - the ip address of the DNS server to query (default is system specified nameservers in, e.g. /etc/resolv.conf).lookup_calbackis a Function - the “lookup” event function.This is equivalent to the following:
var net = require("rampart-net"); function resolve_async(hn, cb) { var resolver = new net.Resolver(); resolver.resolve(hn, cb); return resolver; } var resolver = resolve_async(host, callback);
net.reverse_async()¶
Short cut for
new net.Resolver()andresolver.reverse().Usage:
var net = require("rampart-net"); var resolver = net.reverse_async(ip_addr[, nameserver], lookup_callback);Where:
ip_addris a String - the ip address to look up.nameserveris a String - the ip address of the DNS server to query (default is system specified nameservers in, e.g. /etc/resolv.conf).lookup_calbackis a Function - the “lookup” event function.This is equivalent to the following:
var net = require("rampart-net"); function reverse_async(ip, cb) { var resolver = new net.Resolver(); resolver.reverse(ip, cb); return resolver; } var resolver = reverse_async(ip, callback);