Skip to content

Latest commit

 

History

History
1634 lines (1177 loc) · 74 KB

File metadata and controls

1634 lines (1177 loc) · 74 KB

Classes

JSONObjectBufferEventEmitter

Object Buffer for JSON encoding

de/serialize objects to/from a Buffer

Automatically reassembles fragmented buffers (useful when the buffer passes through a socket, for example, and is received in pieces) and gives you your object back

ObjectBufferEventEmitter

Object Buffer for encoding

de/serialize objects to/from a Buffer

Automatically reassembles fragmented buffers (useful when the buffer passes through a socket, for example, and is received in pieces) and gives you your object back

SockhopClientEventEmitter

Wrapped TCP client

SockhopErrorError

Custom sockhop errors

Error types, should only change with major versions

  • ERR_MULTICONNECT : attempting to call connect while a socket is already connecting
  • ERR_SOCKET_DESTROYED : attempting to interact with a destroyed socket
  • ERR_REMOTE_CALLBACK_TYPE : attempting to use remote callbacks with wrong message types, or not a callback function
  • ERR_REQUEST_TYPE : attempting to use requests with wrong message types
  • ERR_NO_SOCKET : attempting to send a message with no socket
  • ERR_BAD_DATA : attempting to send a message with no data payload
  • ERR_OBJECTBUFFER_BAD_BUFFER : attempting to do a buffer operation with a non-buffer
  • ERR_OBJECTBUFFER_BAD_BUFFER_DATA : attempting to do a buffer operation with bad data in the buffer
  • ERR_OBJECTBUFFER_BAD_OBJECT : attempting to do an object operation with a non-serializable object
  • ERR_RESPONSE_TIMEOUT : the response timed out
  • ERR_RESPONSE_SEND : the response could not be sent
SockhopPing

TCP Ping

Used internally when .ping() is called

SockhopPong

TCP Ping reply

Used internally when .ping() is replied

SockhopServerEventEmitter

Wrapped TCP server

When data is received by the server, the received Buffer is concatenated with previously received Buffers until a delimiter (usually "\n") is received. The composite Buffer is then treated like a JSON string and converted to an object, which is triggers a "receive" event. If the client is a SockhopClient, it will further wrap sent data in metadata that describes the type - this allows you to pass custom objects (prototypes) across the wire, and the other end will know it has received your Widget, or Foo, or whatever. Plain objects, strings, etc. are also similarly labelled. The resulting receive event has a "meta" parameter; meta.type will list the object type.

Of course, if your client is not a SockhopClient, you don't want this wrapping/unwrapping behavior and you might want a different delimiter for JSON. Both these parameters are configurable in the constructor options.

SockhopSessionEventEmitter

Base class wrapper for server-side sockets

When a new connection is received by the server, the server will wrap that socket with an instance of this (or child of this) class -- configurable with the session_type option in the server's constructor. This class allows for arbitrary user-data to be assigned to the clients (for example, authentication state information) without having to abuse the underlying net.Socket object.

This class does almost nothing, apart from holding internal references to the net.Socket and SockhopServer instances, and is really intended to be extended. As such, there are several 'virtual' methods included here, which users are encouraged to implement for their specific application.

Sessions are the preferred way for users to interact with client connections, in that users should write child classes which inhert from this base class to interact with the net.Socket instance, and then have their applications call the session methods, rather than calling socket methods directly. For instance, users are discouraged from directly calling socket.end() to terminate clients connection from the server. Rather, users should call session.kill().

JSONObjectBuffer ⇐ EventEmitter

Object Buffer for JSON encoding

de/serialize objects to/from a Buffer

Automatically reassembles fragmented buffers (useful when the buffer passes through a socket, for example, and is received in pieces) and gives you your object back

Kind: global class
Extends: EventEmitter

new JSONObjectBuffer(opts)

Constructs a new JSONObjectBuffer

Param Type Default Description
opts object the options
[opts.terminator] string | array ""\n"" the terminator to signal the end of a JSON object. If an array is given, the first element is a receive (buf2obj) terminator and the second is the transmit (obj2buf) element
[opts.allow_non_objects] boolean false allow non objects in buf2obj (will be passed through as Strings)

jsonObjectBuffer.buf2obj(buffer) ⇒ Array

buf2obj

Convert a Buffer into one or more objects

Kind: instance method of JSONObjectBuffer
Returns: Array - found the objects we found

Param Type Description
buffer Buffer the buffer to read (we may modify or store it!)

jsonObjectBuffer.obj2buf(object, buffer)

obj2buf

Convert an Object to a Buffer

Kind: instance method of JSONObjectBuffer

Param Type Description
object Object the object to convert
buffer Buffer the buffer representing that object

ObjectBuffer ⇐ EventEmitter

Object Buffer for encoding

de/serialize objects to/from a Buffer

Automatically reassembles fragmented buffers (useful when the buffer passes through a socket, for example, and is received in pieces) and gives you your object back

Kind: global class
Extends: EventEmitter

new ObjectBuffer(opts)

Constructs a new ObjectBuffer

Param Type Description
opts object the options

objectBuffer.buf2obj(buffer) ⇒ Array

buf2obj

Convert a Buffer into one or more objects

Kind: instance method of ObjectBuffer
Returns: Array - found the objects we found

Param Type Description
buffer Buffer the buffer to read (we may modify or store it!)

objectBuffer.obj2buf(name, object, buffer)

obj2buf

Convert an Object to a Buffer

Kind: instance method of ObjectBuffer

Param Type Description
name string the name of the schema to use
object Object the object to convert
buffer Buffer the buffer representing that object

SockhopClient ⇐ EventEmitter

Wrapped TCP client

Kind: global class
Extends: EventEmitter
Emits: connect, disconnect, handshake, unhandshake, debug:sending, debug:sending:buffer, debug:received, debug:received:buffer, binary_mode:rx, binary_mode:tx, SockhopClient#event:error, receive, receive:buffer, event:SockhopError

new SockhopClient([opts])

Constructs a new SockhopClient

For the 2.x libarary version, it is strongly recommended that you use handshake-based connections and events for managing lifecycle:

const client = new Sockhop.Client({ auto_rehandshake: true });
await client.start(); // Waits for handshake to complete

client.binary_mode.tx; // has a definite value, now that the handshake is complete

client.on("handshake", (success, error) => {
   // Can catch errors where, or handle re-connections
});

client.on("unhandshake", () => {
  // Handle when a handshaked-connection is lost
});

await client.disconnect();

That being said, if you are trying to interoperate with a 1.x/compatibility mode remote, many of the above methods/events will mis-behave, since the handshake doesn't success with a 1.x/compatibility mode remote. In that case, you will need to handle both cases:

const client = new Sockhop.Client({ auto_reconnect: true });

client.on("receive", (obj, meta) => {
  // Attach handlers *before* calling connect, since 1.x/compatibility mode remotes can start sending data immediately after the connect event

  // If you want to differentiate, you can switch on client.handshake_successful or client.binary_mode.rx == true
  if ( client.handshake_successful ) {
     // 2.x+ client
  } else {
     // 1.x/compatibility mode client
  }
});

// await client.start(); // This will throw an error if the remote is 1.x/compatibility mode
await client.connect(); // Does not wait for handshake to complete

client.on("handshake", (success, error) => {
  // Use this for reconnctions, and to differentiate between 2.x+ and 1.x/compatibility mode remotes:
  // Check for error.code=="ERR_HANDSHAKE_TIMEOUT"

  if ( success ) {
    // 2.x+ client
  } else if (error.code=="ERR_HANDSHAKE_TIMEOUT") {
    // 1.x/compatibility mode remote
  } else {
    // Handle error
  }
});


// client.on("unhandshake", () => {}); // Only fires for 2.x+ handshaked-connection lost:
client.on("disconnect", (sock, handshaked) => {
  if ( handshaked ) {
    // 2.x+ handshaked-connection lost, same as unhandshake event
  } else {
    // Handle 1.x/compatibility or 2.x+failed handshake disconnects
  }
});

await client.disconnect(); // Disconnects cleanly

If you would rather skip the complexity, and just have this library behave like 1.x, you can enable compatibility mode, though, this will totally disable all handshake-related features.

const client = new Sockhop.Client({ compatibility_mode: true, auto_reconnect: true });

await client.connect(); // Does not even attempt a handshake, nor waits for one

client.binary_mode.tx; // will always be false, since we are not doing a handshake

// client.on("handshake", (success, error) => {}); // this will never fire
client.on("connect", () => {
  // but this will!
});

// client.on("unhandshake", () => {}); // Also will never fire
client.on("disconnect", (sock, handshaked) => {
  handshaked; // will always be false
});

await client.disconnect(); // Disconnects cleanly

Throws:

Param Type Default Description
[opts] object an object containing configuration options
[opts.path] string the path for a Unix domain socket. If used, this will override the address and port values.
[opts.address] string ""127.0.0.1"" the IP address to bind to
[opts.port] number 50000 the TCP port to use
[opts.ssl] boolean false use tls
[opts.ssl_options] object {} options to pass to the tls socket constructor, see tls.connect for details, note, if any options are provided, the opts.ssl flag is overriden as true
[opts.auto_rehandshake] number false automatically try to rehandshake if the connection is lost (overrides auto_reconnect if both are set)
[opts.auto_reconnect] number false automatically try to reconnect if the connection is lost
[opts.auto_reconnect_interval] number 2000 the auto reconnection interval, in ms.
[opts.auto_rehandshake_interval] number 5000 the auto reconnection interval, in ms.
[opts.auto_reconnect_requires_handshake] boolean true have reconnections fail unless the handshake completes successfully
[opts.terminator] string | array ""\n"" the JSON object delimiter. Passed directly to the JSONObjectBuffer constructor.
[opts.allow_non_objects] boolean false allow non objects to be received and transmitted. Passed directly to the JSONObjectBuffer constructor.
[opts.connect_timeout] number 5000 the length of time in ms to try to connect before timing out
[opts.debug] boolean false run in debug mode -- which adds additional emits
[opts.handshake_timeout] number 3000 the length of time in ms to wait for a handshake response before timing out
[opts.compatibility_mode] boolean false enable compatibility mode, which will disable handshakes for simulating 1.x behavior
[opts.allow_binary_mode] boolean true request binary mode during handshake (ignored in compatibility mode)

sockhopClient.connected ⇒ boolean

connected

Kind: instance property of SockhopClient
Returns: boolean - connected whether or not we are currently connected (e.g. can data be sent)

sockhopClient.auto_reconnect ⇒ boolean

auto_reconnect getter

Kind: instance property of SockhopClient
Returns: boolean - auto_reconnect the current auto_reconnect setting

sockhopClient.auto_rehandshake ⇒ boolean

auto_rehandshake getter

Kind: instance property of SockhopClient
Returns: boolean - auto_reconnect the current auto_reconnect setting

sockhopClient.auto_reconnect

auto_reconnect setter

Kind: instance property of SockhopClient

Param Type Description
auto_reconnect boolean the desired auto_reconnect setting

sockhopClient.debug ⇒ boolean

debug mode getter

Kind: instance property of SockhopClient
Returns: boolean - debug whether or not we are in debug mode

sockhopClient.compatibility_mode ⇒ boolean

compatibility_mode getter

Kind: instance property of SockhopClient
Returns: boolean - compatibility_mode whether or not we are in compatibility mode

sockhopClient.handshake_successful ⇒ boolean

handshake_successful getter

NOTE : this will be false if the handshake has not yet completed, or if the client is in compatibility mode

Kind: instance property of SockhopClient
Returns: boolean - handshake_successful whether or not the last handshake was successful

sockhopClient.init_complete ⇒ boolean

init_complete getter

NOTE : this will be true if the client is in compatibility mode and connected, since no handshake is expected

Kind: instance property of SockhopClient
Returns: boolean - init_complete is the client still expecting to run more initialization steps (e.g. handshake)

sockhopClient.binary_mode ⇒ object | boolean | boolean

binary_mode getter

Kind: instance property of SockhopClient
Returns: object - binary_mode the current binary mode statusboolean - binary_mode.rx true if we are receiving in binary modeboolean - binary_mode.tx true if we are transmitting in binary mode

sockhopClient.socket : net.socket

Underlying net.socket

Kind: instance property of SockhopClient

sockhopClient._perform_auto_reconnect()

Perform an auto reconnet (internal)

We have determined that an auto reconnect is necessary. We will initiate it, and manage the fallout.

Kind: instance method of SockhopClient

sockhopClient._perform_auto_rehandshake()

Perform an auto rehandshake (internal)

We have determined that an auto rehandshake is necessary. We will initiate it, and manage the fallout.

Kind: instance method of SockhopClient

sockhopClient.start() ⇒ Promise

Start a connection to the server (including handshake)

NOTE : this requires a "clean" start, meaning we are neither connected nor trying to connect.

This method will only resolve if the handshake completes successfully, otherwise it will reject (similar to how connect() will throw if the connection fails). This also means that if the connection succeeds, but the handshake fails or times out, this will reject, and the connection will be closed.

If you want to keep trying until you connect and handshake successfully, you will want to set auto_reconnect to true, and then call this method in a loop with a try/catch block, since this method will throw if the connection or handshake fails.

If you are interoperating with a 1.x/compatibility mode remote, you should not use this method, since it will always throw, instead you should use .connect() but add your own listener to the handshake event and check handle success/failure there. See the handshake event docs for more information.

NOTE : if auto_reconnect is enabled, it will only start trying to reconnect once the handshake completes successfully. however, the reconnections do not guarentee that the handshake will succeed, so you should still listen for the 'handshake' event. Even better would be to set auto_rehandshake to true, which will try to rehandshake automatically if the connection is lost. However, that workflow doesn't play nicely with interoperating with 1.x/compatibility mode remotes, since the handshake will never succeed.

WARNING: if the other side of the connection get's a connect event, they can begin sending data immediately, so if there are issues with the handshake, you could end up in bad sitaution of the other side repeatedly sending data that you are ignoring.

Kind: instance method of SockhopClient
Returns: Promise - resolves once connected and handshake completes
Throws:

sockhopClient.connect() ⇒ Promise

Connect

WARNING: this does not wait for the handshake to complete. Unless you are in compatibility mode or trying to interoperate with a 1.x remote, you should probably use .start() instead, which will wait for the handshake to complete. See notes below and on the handshake event for more information.

Attempt to connect to the server. If we are already connected, this returns immediately. If we are already trying to connect, this throws an error. If this client has been configured for auto_reconnect, it will start a reconnection timer only once connected.

if this client has been configured with auto_rehandshake, this method will throw an error, since you almost certainly want .start() instead. If you are very certian you want to use .connect() with auto_rehandshake, you can call the internal ._connect() method instead.

If you want to keep trying until you connect, you will want to set auto_reconnect to true, and then call this method in a loop with a try/catch block, since this method will throw if the connection fails.

NOTE : this method does not wait for the handshake to complete. You should listen for the 'handshake' event to determine if the handshake was successful, or use the .resolve_on_handshake() method to get a promise that resolves once the handshake completes.

Kind: instance method of SockhopClient
Returns: Promise - resolves once connected
Throws:

sockhopClient.get_bound_address() ⇒ string

Get bound address

Kind: instance method of SockhopClient
Returns: string - the IP address we are bound to

sockhopClient.send(object, [rcallback]) ⇒ Promise

Send

This will appear on the remote side as a receive event

Send an object to the server

Kind: instance method of SockhopClient
Throws:

Param Type Description
object object to be sent over the wire
[rcallback] function Callback when remote side calls meta.callback (see receive event) - this is basically a remote Promise

sockhopClient.send_typed_buffer(type, buff, [callback]) ⇒ Promise

Send a buffer with a type descriptor

This will appaer on the remote side as a receive:buffer event

Kind: instance method of SockhopClient
Throws:

Param Type Description
type string a type name for what the buffer encodes
buff Buffer the buffer to send
[callback] function Callback when remote side calls meta.callback (see receive event) - this is basically a remote Promise

sockhopClient.ping(delay)

Ping

Send ping, detect timeouts. If we have 4 timeouts in a row, we kill the connection and emit a 'disconnect' event. You can then call .connect() again to reconnect.

Kind: instance method of SockhopClient

Param Type Default Description
delay number 0 in ms (0 disables ping)

sockhopClient.disconnect() ⇒ Promise

disconnect

Disconnect the socket (send FIN) Pinging will also be turned off... if you want to keep pinging, you will need to call .ping() again after you connect again

Kind: instance method of SockhopClient

"connect" (sock)

connect event

this fires when we have successfully connected to the server, but before the handshake completes/times-out.

NOTE : unless you are in compatibility mode or trying to interoperate with a 1.x remote, you should probably wait for the handshake event instead of connect. See discussion in the handshake event docs for more information

Kind: event emitted by SockhopClient

Param Type Description
sock net.Socket the socket that just connected

"handshake" (success, error)

handshake event

This fires when the handshake completes or times out

WARNING: if the other side of the connection get's a connect event, they can begin sending data immediately. regardless of whether or not the handshake completes or times out, or is simply ignored (compatibility mode or 1.x library version). This means data can be sent before the handshake completes, unless both sides have agreed to wait for the handshake event before sending any data. It is recommnded that in situations where you cannot gaurantee that both sides are using Sockhop 2.x with handshakes, that you should listen for the connection event for the purpose of adding event handlers, but wait for the handshake event to proactively send any data, so that the send logic can depending on a know handshake state. This will have the added benefit of ensuring that you will not try to tx until the binary mode negotiation is complete, (which finish immediately before the handshake event fires). Finally, this will allow a smooth transition when all 1.x/compoatibility mode clients are upgraded to 2.x with handshakes, since in that case, both sides will already be waiting for the handshake event before sending any data.

Kind: event emitted by SockhopClient

Param Type Description
success boolean true if the handshake was successful, false if it timed out or failed
error Error if the handshake failed, this will contain the error, otherwise undefined

"unhandshake"

unhandshake event

This fires when we were previously handshaked, but the connection was lost. This is analogous to the disconnect event, but only fires if we were previously handshaked. If you are interoperating with a 1.x/compatibility mode remote, this event will not fire, since the handshake will never succeed.

Kind: event emitted by SockhopClient

"receive" (object, meta)

receive object event

We have successfully received an object from the server

Kind: event emitted by SockhopClient

Param Type Description
object object the received object
meta object metadata
meta.type string the received object constructor ("Object", "String", "Widget", etc)
meta.callback function if the received object was sent with a callback, this is the function to call to respond

"receive:buffer" (buffer, meta)

receive a typed buffer event

We have successfully received a buffer from the server

NOTE : this will only fire in binary mode (rx) and if the remote end specifically called send_typed_buffer(). If instead the remote end called send() with a Buffer, you will get a normal 'receive' event with the type set to "Buffer".

Kind: event emitted by SockhopClient

Param Type Description
buffer Buffer the received buffer
meta object metadata
meta.type string the received buffer type ("String", "Widget", etc)
meta.callback function if the received object was sent with a callback, this is the function to call to respond

"disconnect" (sock, handshaked)

disconnect event

This fires when we have disconnected from the server, either because the server closed the connection, or because we called disconnect(). If we were previously handshaked, the unhandshake event will fire first, followed by this event.

Kind: event emitted by SockhopClient

Param Type Description
sock net.Socket the socket that just disconnected
handshaked boolean true if we were previously handshaked, false otherwise

"debug:sending" (object, buffer, binary_mode)

sending event

NOTE : This event is only emitted if the SockhopClient is in debug mode

Kind: event emitted by SockhopClient

Param Type Description
object object the object we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode

"debug:received" (object, buffer, binary_mode)

received event

NOTE : This event is only emitted if the SockhopClient is in debug mode

Kind: event emitted by SockhopClient

Param Type Description
object object the object we just received
buffer Buffer the buffer we just received
binary_mode boolean true if we are receiving in binary mode

"debug:sending:buffer" (object, buffer, binary_mode)

sending typed buffer event

NOTE : This event is only emitted if the SockhopClient is in debug mode

Kind: event emitted by SockhopClient

Param Type Description
object object the object we are sending
object.data Buffer type typed buffer we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode (should always be true)

"debug:received:buffer" (object, buffer, binary_mode)

received typed buffer event

NOTE : This event is only emitted if the SockhopClient is in debug mode

Kind: event emitted by SockhopClient

Param Type Description
object object the object we just received
object.data object.data the typed buffer we just received
buffer Buffer the (raw) buffer we just received over the wire
binary_mode boolean true if we are receiving in binary mode (should always be true)

"binary_mode:rx" (enabled)

binary_mode:rx object event

If true, the other end of the connection will (from this packet onward) be sending us data in binary mode

If false, the other end of the connection was reset, and so a renegotiation of binary mode may be necessary both the other side will be sending in binary mode again.

NOTE : the true variant of this event has undetermined ordering with respect to the firing of handshake, meaning it could fire before or after handshake, depending on network timing. This is largely irrelevant, since the this event is related to how the library internally handles parsing incoming data, and not how we send data. Think of this event as informational only about the state of the other side of the connection.

Kind: event emitted by SockhopClient

Param Type Description
enabled boolean true if we are now receiving in binary mode

"binary_mode:tx" (enabled)

binary_mode:tx object event

If true, we will (from this packet onward) be sending data in binary mode.

If false, the connection was reset, and so a renegotiation of binary mode may be necessary before we can send data in binary mode again.

NOTE : if the handshake fails or times out, this event will not fire with false, since we are already not in binary mode. However, you can always check the state of binary mode using the .binary_mode.tx property. The false event will fire on any disconnect if the system was in binary mode to begih with

NOTE : the true variant of this event will always fire before the handshake event, which means that you don't need to wait for both this event and handshake to know that your tx-ing data encoding has settled. As a result, you can probably ignore this event entirely, unless you are doing something really low-level.

Kind: event emitted by SockhopClient

Param Type Description
enabled boolean true if we are now receiving in binary mode

SockhopError ⇐ Error

Custom sockhop errors

Error types, should only change with major versions

  • ERR_MULTICONNECT : attempting to call connect while a socket is already connecting
  • ERR_SOCKET_DESTROYED : attempting to interact with a destroyed socket
  • ERR_REMOTE_CALLBACK_TYPE : attempting to use remote callbacks with wrong message types, or not a callback function
  • ERR_REQUEST_TYPE : attempting to use requests with wrong message types
  • ERR_NO_SOCKET : attempting to send a message with no socket
  • ERR_BAD_DATA : attempting to send a message with no data payload
  • ERR_OBJECTBUFFER_BAD_BUFFER : attempting to do a buffer operation with a non-buffer
  • ERR_OBJECTBUFFER_BAD_BUFFER_DATA : attempting to do a buffer operation with bad data in the buffer
  • ERR_OBJECTBUFFER_BAD_OBJECT : attempting to do an object operation with a non-serializable object
  • ERR_RESPONSE_TIMEOUT : the response timed out
  • ERR_RESPONSE_SEND : the response could not be sent

Kind: global class
Extends: Error

new SockhopError(message, code)

Constructs a new SockhopError

Param Type Description
message string A message string describing the error
code string A standardized code for filtering error types

SockhopPing

TCP Ping

Used internally when .ping() is called

Kind: global class

sockhopPing.unanswered() ⇒ boolean

Unanswered

Is this ping Unanswered?

Kind: instance method of SockhopPing

sockhopPing.conclude_with_pong(pong)

Conclude a ping

Sets the returned, finished values

Kind: instance method of SockhopPing

Param Type Description
pong SockhopPong the pong (ping reply) that is finishing this ping

SockhopPong

TCP Ping reply

Used internally when .ping() is replied

Kind: global class

SockhopServer ⇐ EventEmitter

Wrapped TCP server

When data is received by the server, the received Buffer is concatenated with previously received Buffers until a delimiter (usually "\n") is received. The composite Buffer is then treated like a JSON string and converted to an object, which is triggers a "receive" event. If the client is a SockhopClient, it will further wrap sent data in metadata that describes the type - this allows you to pass custom objects (prototypes) across the wire, and the other end will know it has received your Widget, or Foo, or whatever. Plain objects, strings, etc. are also similarly labelled. The resulting receive event has a "meta" parameter; meta.type will list the object type.

Of course, if your client is not a SockhopClient, you don't want this wrapping/unwrapping behavior and you might want a different delimiter for JSON. Both these parameters are configurable in the constructor options.

Kind: global class
Extends: EventEmitter
Emits: connect, disconnect, unhandshake, receive, receive:buffer, handshake, debug:sending, debug:sending:buffer, debug:received, debug:received:buffer, event:SockhopError

new SockhopServer([opts])

Constructs a new SockhopServer

Param Type Default Description
[opts] object an object containing configuration options
[opts.path] string the path for a Unix domain socket. If used, this will override the address and port values.
[opts.address] string ""127.0.0.1"" the IP address to bind to
[opts.port] number 50000 the TCP port to use
[opts.terminator] string | array ""\n"" the JSON object delimiter. Passed directly to the JSONObjectBuffer constructor.
[opts.allow_non_objects] boolean false allow non objects to be received and transmitted. Passed directly to the JSONObjectBuffer constructor.
[opts.session_type] Object SockhopSession the identifier for a SockhopSession class (or inhereted class)
[opts.handshake_timeout] number 3000 the length of time in ms to wait for a handshake response before timing out
[opts.compatibility_mode] boolean false enable compatibility mode, which will disable handshakes for simulating 1.x behavior
[opts.debug] boolean false run in debug mode -- which adds additional emits
[opts.allow_binary_mode] boolean true request binary mode during handshake (ignored in compatibility mode)

sockhopServer.sockets : Array.<net.Socket>

Socket getter

Kind: instance property of SockhopServer

sockhopServer.sessions : Array.<SockhopSession>

Session getter

Kind: instance property of SockhopServer

sockhopServer.compatibility_mode ⇒ boolean

compatibility_mode getter

Kind: instance property of SockhopServer
Returns: boolean - compatibility_mode whether or not we are in compatibility mode

sockhopServer.debug ⇒ boolean

debug mode getter

Kind: instance property of SockhopServer
Returns: boolean - debug whether or not we are in debug mode

sockhopServer.emit_async()

Emit async

We end up with odd event loops sometimes, e.g. if an on("disconnect") calls .sendall(), another "disconnect" will be emitted. This functon emits evens asynchronously and breaks the chain //HACK -- THIS IS A HACKY FIX -- //HACK

Kind: instance method of SockhopServer

sockhopServer.ping(delay)

Ping

Ping all clients, detect timeouts. Only works if connected to a SockhopClient.

Kind: instance method of SockhopServer

Param Type Default Description
delay number 0 in ms (0 disables ping)

sockhopServer.listen() ⇒ Promise.<net.server>

Listen

Bind and wait for incoming connections

Kind: instance method of SockhopServer

sockhopServer.get_bound_address() ⇒ string

Get bound address

Kind: instance method of SockhopServer
Returns: string - the IP address we are bound to

sockhopServer.send(socket, object, [callback]) ⇒ Promise

Send

This will appear on the remote side as a receive event

Send an object to one clients

Kind: instance method of SockhopServer
Throws:

  • SockhopError
Param Type Description
socket net.socket on which to send it
object object that we want to send
[callback] function Callback when remote side calls meta.done (see receive event) - this is basically a remote Promise

sockhopServer.send_typed_buffer(socket, type, buff, [callback]) ⇒ Promise

Send a buffer with a type descriptor

This will appaer on the remote side as a receive:buffer event

Kind: instance method of SockhopServer
Throws:

Param Type Description
socket net.socket on which to send it
type string a type name for what the buffer encodes
buff Buffer the buffer to send
[callback] function Callback when remote side calls meta.callback (see receive event) - this is basically a remote Promise

sockhopServer.sendall(object) ⇒ Promise

Sendall

Send an object to all clients

Kind: instance method of SockhopServer

Param Type Description
object object to send to all connected clients

sockhopServer.kill_socket(sock) ⇒ Promise

Stops a client connection

Kind: instance method of SockhopServer

Param Type Description
sock net.Socket the client socket to kill

sockhopServer.disconnect() ⇒ Promise

Disconnect

Disconnect all clients Does not close the server - use close() for that

Kind: instance method of SockhopServer
Returns: Promise - resolves when all sockets are killed

sockhopServer.close() ⇒ Promise

Close

Disconnects any clients and closes the server

Kind: instance method of SockhopServer
Returns: Promise - resovles when all sockets are killed and the server closed

"connect" (sock, session)

connect event

this fires when we have successfully connected to the client, but before the handshake completes/times-out

NOTE : unless you are in compatibility mode or trying to interoperate with a 1.x remote, you should probably wait for the handshake event instead of connect. See discussion in the handshake event docs for more information

Kind: event emitted by SockhopServer

Param Type Description
sock net.Socket the socket that just connected
session SockhopSession the session of the socket

"handshake" (sock, session, success, error)

handshake event

This fires when the handshake completes or times out

WARNING: if the other side of the connection get's a connect event, they can begin sending data immediately. regardless of whether or not the handshake completes or times out, or is simply ignored (compatibility mode or 1.x library version). This means data can be sent before the handshake completes, unless both sides have agreed to wait for the handshake event before sending any data. It is recommnded that in situations where you cannot gaurantee that both sides are using Sockhop 2.x with handshakes, that you should listen for the connection event for the purpose of adding event handlers, but wait for the handshake event to proactively send any data, so that the send logic can depending on a know handshake state. This will have the added benefit of ensuring that you will not try to tx until the binary mode negotiation is complete, (which finish immediately before the handshake event fires). Finally, this will allow a smooth transition when all 1.x/compoatibility mode clients are upgraded to 2.x with handshakes, since in that case, both sides will already be waiting for the handshake event before sending any data.

Kind: event emitted by SockhopServer

Param Type Description
sock net.Socket the socket that just connected
session SockhopSession the session of the socket
success boolean true if the handshake was successful, false if it timed out or failed
error Error if the handshake failed, this will contain the error, otherwise undefined

"receive" (object, meta)

receive object event

We have successfully received an object from the client

Kind: event emitted by SockhopServer

Param Type Description
object object the received object
meta object metadata
meta.type string the received object constructor ("Object", "String", "Widget", etc)
meta.socket net.Socket the socket that sent us this object
meta.session SockhopSession the session of the socket
[meta.callback] function the callback function, if the client is requesting a callback. Pass an object you want returned to the client

"receive:buffer" (buffer, meta)

receive buffer event

We have successfully received a buffer from the server

NOTE : this will only fire in binary mode (rx) and if the remote end specifically called send_typed_buffer(). If instead the remote end called send() with a Buffer, you will get a normal 'receive' event with the type set to "Buffer".

Kind: event emitted by SockhopServer

Param Type Description
buffer Buffer the received buffer
meta object metadata
meta.type string the received buffer type ("String", "Widget", etc)
meta.socket net.Socket the socket that sent us this object
meta.session SockhopSession the session of the socket
meta.callback function if the received object was sent with a callback, this is the function to call to respond

"disconnect" (sock, session, handshaked)

disconnect event

Kind: event emitted by SockhopServer

Param Type Description
sock net.Socket the socket that just disconnected
session SockhopSession the session of the socket
handshaked boolean true if we were previously handshaked, false otherwise

"unhandshake" (sock, session)

unhandshake event

This fires when we were previously handshaked, but the connection was lost. This is analogous to the disconnect event, but only fires if we were previously handshaked. If you are interoperating with a 1.x/compatibility mode remote, this event will not fire, since the handshake will never succeed.

Kind: event emitted by SockhopServer

Param Type Description
sock net.Socket the socket that just disconnected
session SockhopSession the session of the socket

"debug:sending" (object, buffer, binary_mode, sock, session)

sending event

NOTE : This event is only emitted if the SockhopServer is in debug mode

Kind: event emitted by SockhopServer

Param Type Description
object object the object we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode
sock net.Socket the socket we are sending on
session SockhopSession the session of the socket

"debug:received" (object, buffer, binary_mode, sock, session)

received event

NOTE : This event is only emitted if the SockhopServer is in debug mode

Kind: event emitted by SockhopServer

Param Type Description
object object the object we just received
buffer Buffer the buffer we just received
binary_mode boolean true if we are receiving in binary mode
sock net.Socket the socket we are receiving on
session SockhopSession the session of the socket

"debug:sending:buffer" (object, buffer, binary_mode, sock, session)

sending typed buffer event

NOTE : This event is only emitted if the SockhopServer is in debug mode

Kind: event emitted by SockhopServer

Param Type Description
object object the object we are sending
object.data Buffer type typed buffer we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode (should always be true)
sock net.Socket the socket we are sending on
session SockhopSession the session of the socket

"debug:received:buffer" (object, buffer, binary_mode, sock, session)

received typed buffer event

NOTE : This event is only emitted if the SockhopServer is in debug mode

Kind: event emitted by SockhopServer

Param Type Description
object object the object we just received
object.data object.data the typed buffer we just received
buffer Buffer the (raw) buffer we just received over the wire
binary_mode boolean true if we are receiving in binary mode (should always be true)
sock net.Socket the socket we are receiving on
session SockhopSession the session of the socket

SockhopSession ⇐ EventEmitter

Base class wrapper for server-side sockets

When a new connection is received by the server, the server will wrap that socket with an instance of this (or child of this) class -- configurable with the session_type option in the server's constructor. This class allows for arbitrary user-data to be assigned to the clients (for example, authentication state information) without having to abuse the underlying net.Socket object.

This class does almost nothing, apart from holding internal references to the net.Socket and SockhopServer instances, and is really intended to be extended. As such, there are several 'virtual' methods included here, which users are encouraged to implement for their specific application.

Sessions are the preferred way for users to interact with client connections, in that users should write child classes which inhert from this base class to interact with the net.Socket instance, and then have their applications call the session methods, rather than calling socket methods directly. For instance, users are discouraged from directly calling socket.end() to terminate clients connection from the server. Rather, users should call session.kill().

Kind: global class
Extends: EventEmitter
Emits: handshake, unhandshake, disconnect, receive, receive:buffer, debug:sending, debug:received, binary_mode:rx, binary_mode:tx

new SockhopSession(sock, server)

Constructor

By default, I just save references to the socket and the server

Param Type Description
sock net.Socket the socket object
server SockhopServer a reference to the SockhopServer

sockhopSession.sock : net.Socket

Getter for the underlying session socket

Kind: instance property of SockhopSession

sockhopSession.server : SockhopServer

Getter for the server

Kind: instance property of SockhopSession

sockhopSession.init_complete ⇒ boolean

init_complete getter

NOTE : this will be true if the client is in compatibility mode and connected, since no handshake is expected

Kind: instance property of SockhopSession
Returns: boolean - init_complete is the client still expecting to run more initialization steps (e.g. handshake)

sockhopSession.binary_mode ⇒ object | boolean | boolean

binary_mode getter

Kind: instance property of SockhopSession
Returns: object - binary_mode the current binary mode statusboolean - binary_mode.rx true if we are receiving in binary modeboolean - binary_mode.tx true if we are transmitting in binary mode

sockhopSession.handshake_successful ⇒ boolean

handshake_successful getter

NOTE : this will be false if the handshake has not yet completed, or if the client is in compatibility mode

Kind: instance property of SockhopSession
Returns: boolean - handshake_successful whether or not the last handshake was successful

sockhopSession.send_typed_buffer(type, buff, [callback]) ⇒ Promise

Send a buffer with a type descriptor

This will appaer on the remote side as a receive:buffer event

Kind: instance method of SockhopSession
Throws:

Param Type Description
type string a type name for what the buffer encodes
buff Buffer the buffer to send
[callback] function Callback when remote side calls meta.callback (see receive event) - this is basically a remote Promise

sockhopSession.send(obj, [callback]) ⇒ Promise

Send a message over this session

This will appear on the remote side as a receive event

Kind: instance method of SockhopSession
Returns: Promise - resolves on send
Throws:

Param Type Description
obj object
[callback] function Callback when remote side calls meta.done (see receive event) - this is basically a remote Promise

sockhopSession.kill() ⇒ Promise

Kill this session

Kind: instance method of SockhopSession
Returns: Promise - resolves on socket end

sockhopSession.start() ⇒ Promise

Start this session

Override me to do any setup of the session.

I get called internally by the SockhopServer immediately after a new client connects to the server, before the server emits the 'connect' event. (before even the socket gets registered in the server's server._sockets list).

Kind: instance abstract method of SockhopSession
Returns: Promise - resolves when setup is complete

sockhopSession.end() ⇒ Promise

End this session

Override me to do any teardown of the session

I get called internally by the SockhopServer immediately after the client's socket emits the 'end' event, and when I resolve, I then trigger the server to emit the 'disconnect' event.

Kind: instance abstract method of SockhopSession
Returns: Promise - resolves when teardown is complete

"handshake" (success, error)

handshake event

This fires when the handshake completes or times out

WARNING: if the other side of the connection get's a connect event, they can begin sending data immediately. regardless of whether or not the handshake completes or times out, or is simply ignored (compatibility mode or 1.x library version). This means data can be sent before the handshake completes, unless both sides have agreed to wait for the handshake event before sending any data. It is recommnded that in situations where you cannot gaurantee that both sides are using Sockhop 2.x with handshakes, that you should listen for the connection event for the purpose of adding event handlers, but wait for the handshake event to proactively send any data, so that the send logic can depending on a know handshake state. This will have the added benefit of ensuring that you will not try to tx until the binary mode negotiation is complete, (which finish immediately before the handshake event fires). Finally, this will allow a smooth transition when all 1.x/compoatibility mode clients are upgraded to 2.x with handshakes, since in that case, both sides will already be waiting for the handshake event before sending any data.

Kind: event emitted by SockhopSession

Param Type Description
success boolean true if the handshake was successful, false if it timed out or failed
error Error if the handshake failed, this will contain the error, otherwise undefined

"receive" (object, meta)

receive object event

We have successfully received an object from the server

Kind: event emitted by SockhopSession

Param Type Description
object object the received object
meta object metadata
meta.type string the received object constructor ("Object", "String", "Widget", etc)
meta.callback function if the received object was sent with a callback, this is the function to call to respond

"unhandshake"

unhandshake event

This fires when we were previously handshaked, but the connection was lost. This is analogous to the disconnect event, but only fires if we were previously handshaked. If you are interoperating with a 1.x/compatibility mode remote, this event will not fire, since the handshake will never succeed.

Kind: event emitted by SockhopSession

"disconnect" (handshaked)

disconnect event

Kind: event emitted by SockhopSession

Param Type Description
handshaked boolean true if we were previously handshaked, false otherwise

"debug:sending" (object, buffer, binary_mode)

sending event

NOTE : This event is only emitted if the SockhopSession is in debug mode

Kind: event emitted by SockhopSession

Param Type Description
object object the object we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode

"debug:received" (object, buffer, binary_mode)

received event

NOTE : This event is only emitted if the SockhopSession is in debug mode

Kind: event emitted by SockhopSession

Param Type Description
object object the object we just received
buffer Buffer the buffer we just received
binary_mode boolean true if we are receiving in binary mode

"debug:sending:buffer" (object, buffer, binary_mode)

sending typed buffer event

NOTE : This event is only emitted if the SockhopSession is in debug mode

Kind: event emitted by SockhopSession

Param Type Description
object object the object we are sending
object.data Buffer type typed buffer we are sending
buffer Buffer the buffer we are sending
binary_mode boolean true if we are sending in binary mode (should always be true)

"debug:received:buffer" (object, buffer, binary_mode)

received typed buffer event

NOTE : This event is only emitted if the SockhopSession is in debug mode

Kind: event emitted by SockhopSession

Param Type Description
object object the object we just received
object.data object.data the typed buffer we just received
buffer Buffer the (raw) buffer we just received over the wire
binary_mode boolean true if we are receiving in binary mode (should always be true)

"receive:buffer" (buffer, meta)

receive buffer event

We have successfully received a buffer from the server

NOTE : this will only fire in binary mode (rx) and if the remote end specifically called send_typed_buffer(). If instead the remote end called send() with a Buffer, you will get a normal 'receive' event with the type set to "Buffer".

Kind: event emitted by SockhopSession

Param Type Description
buffer Buffer the received buffer
meta object metadata
meta.type string the received buffer type ("String", "Widget", etc)
meta.callback function if the received object was sent with a callback, this is the function to call to respond

"binary_mode:rx" (enabled)

binary_mode:rx object event

The other end of the connection will (from this packet onward) be sending us data in binary mode

NOTE : for the session, this event will never fire with false, since we don't support reconnects on the server side. So in a socket lifecycle, this event might fire exactly once with true in the vacinity of the handshake event.

NOTE : this event is has undetermined ordering with respect to the firing of handshake, meaning it could fire before or after handshake, depending on network timing. This is largely irrelevant, since the this event is related to how the library internally handles parsing incoming data, and not how we send data. Think of this event as informational only about the state of the other side of the connection.

Kind: event emitted by SockhopSession

Param Type Description
enabled boolean true if we are now receiving in binary mode

"binary_mode:tx" (enabled)

binary_mode:tx object event

We will (from this packet onward) be sending data in binary mode.

NOTE : if the handshake fails or times out, this event will not fire with false, since we are already not in binary mode. However, you can always check the state of binary mode using the .binary_mode.tx property.

NOTE : More importantly, for the session, this event will never fire with false, since we don't support reconnects on the server side. So in a socket lifecycle, this event might fire exactly once with true just prior to the handshake event.

NOTE : the true variant of this event will always fire before the handshake event, which means that you don't need to wait for both this event and handshake to know that your tx-ing data encoding has settled. As a result, you can probably ignore this event entirely, unless you are doing something really low-level.

Kind: event emitted by SockhopSession

Param Type Description
enabled boolean true if we are now receiving in binary mode