Node.js socket wrapper which provides variable size framing and request/response association
FramingSocket adds variable size framing to normal sockets.
Note that the FramingSocket assumes a request/response protocol of some form where the first frame bytes are the size of the frame, and each frame response contains an RPC ID to associate it with the sent request. It uses the FramingBuffer internally to handle this framing.
The user can define their own frame_length reader function and rpc_id reader function to find and parse those values from the frame.
It also includes a simplistic back pressure mechanism based on the socket.bufferSize in two stages. warn_buffer_bytes is the first watermark to start telling a user to back off via 'pause' and 'resume' events. max_buffer_bytes is the second watermark where writes will be rejected completely.
Note: Still experimental.
var FramingSocket = require'framing-socket';var socket = ;var rpc_id = 123; // Unique RPC ID to identify this request (unique to this connection)// do something with the returned frame (minus the frame_length bytes)// ....// got what we wanted so let's close the connectionsocketclose;if err// oops - failed to connect...return;socketwriterpc_id 0x01 0x02 0x03 on_frame;socketconnect'localhost' 8888 on_connect;
If you want control of how the fields are read and written:
var FramingSocket = require'framing-socket';// these are actually the defaultsvar options =// Client timeout to use in millisecondstimeout_ms: 5000// memory watermark before emitting 'pause' and 'resume'// events to throttle writes (hopefully)warn_buffer_bytes: 524288// Maximum memory to buffer for a socket before// rejecting writesmax_buffer_bytes: 1048576// frame_length field size in bytesframe_length_size: 4// custom writer function for the frame_length fieldoffset_bufferwriteInt32BEframe_length;// custom function to read the frame_length// note that it passes in an OffsetBuffer (see 'offset-buffer' repo)return offset_bufferreadInt32BE;// rpc_id size in bytesrpc_id_size: 4// custom writer function for the rpc_idoffset_bufferwriteInt32BErpc_id;// custom reader function for the rpc_id// The frame_length field is stripped from this OffsetBuffer alreadyreturn offset_bufferreadInt32BE;;var socket = options;//...
Creates a new socket calls the callback when the connection is complete.
framing_socketconnecthost portif !err// socket is now connected successfully...;
Closes an existing socket. This is a synchronous operation.
Write data to the socket and calls the callback for the response frame. The RPC ID is used to match the request and response together.
var rpc_id = 123;var data = 'abcd' 'utf8';framing_socketwriterpc_id dataif !err// got result frame (OffsetBuffer)! do something with it.;
Fails (rejects) all pending RPCs and calls their callbacks with an err.
var rpc_id = 123;var data = 'abcd' 'utf8';framing_socketwriterpc_id dataif errconsole.log'Oops!';else// shouldn't get here;framing_socketfail_pending_rpcs;// Outputs 'Oops!'
When the connection has an unplanned disconnection. It includes the last detected error object. It is not emitted when close() is called.
framing_socketon'disconnected'// This was unplanned. Try to reconnect?;
When the socket times out. The user can decide to what to do after this.
framing_socketon'timeout'// Socket timed out. Try to reconnect or fail everything?;
Sent when it wants the user to pause upstream events including the server's host/port.
framing_socketon'pause'// Please slow down!;
Sent when the user can continue - including the server's host/port for reference.
framing_socketon'resume'// Ok, go nuts.;
npm install framing-socket