- 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
- 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
- SockhopClient ⇐
EventEmitter Wrapped TCP client
- 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
- SockhopPing
TCP Ping
Used internally when .ping() is called
- SockhopPong
TCP Ping reply
Used internally when .ping() is replied
- 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.
- 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_typeoption 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 callsession.kill().
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
- JSONObjectBuffer ⇐
EventEmitter
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) |
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!) |
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 |
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
- ObjectBuffer ⇐
EventEmitter
Constructs a new ObjectBuffer
| Param | Type | Description |
|---|---|---|
| opts | object |
the options |
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!) |
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 |
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
- SockhopClient ⇐
EventEmitter- new SockhopClient([opts])
- .connected ⇒
boolean - .auto_reconnect ⇒
boolean - .auto_rehandshake ⇒
boolean - .auto_reconnect
- .debug ⇒
boolean - .compatibility_mode ⇒
boolean - .handshake_successful ⇒
boolean - .init_complete ⇒
boolean - .binary_mode ⇒
object|boolean|boolean - .socket :
net.socket - ._perform_auto_reconnect()
- ._perform_auto_rehandshake()
- .start() ⇒
Promise - .connect() ⇒
Promise - .get_bound_address() ⇒
string - .send(object, [rcallback]) ⇒
Promise - .send_typed_buffer(type, buff, [callback]) ⇒
Promise - .ping(delay)
- .disconnect() ⇒
Promise - "connect" (sock)
- "handshake" (success, error)
- "unhandshake"
- "receive" (object, meta)
- "receive:buffer" (buffer, meta)
- "disconnect" (sock, handshaked)
- "debug:sending" (object, buffer, binary_mode)
- "debug:received" (object, buffer, binary_mode)
- "debug:sending:buffer" (object, buffer, binary_mode)
- "debug:received:buffer" (object, buffer, binary_mode)
- "binary_mode:rx" (enabled)
- "binary_mode:tx" (enabled)
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 cleanlyIf 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 cleanlyThrows:
| 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) |
connected
Kind: instance property of SockhopClient
Returns: boolean - connected whether or not we are currently connected (e.g. can data be sent)
auto_reconnect getter
Kind: instance property of SockhopClient
Returns: boolean - auto_reconnect the current auto_reconnect setting
auto_rehandshake getter
Kind: instance property of SockhopClient
Returns: boolean - auto_reconnect the current auto_reconnect setting
auto_reconnect setter
Kind: instance property of SockhopClient
| Param | Type | Description |
|---|---|---|
| auto_reconnect | boolean |
the desired auto_reconnect setting |
debug mode getter
Kind: instance property of SockhopClient
Returns: boolean - debug whether or not we are in debug mode
compatibility_mode getter
Kind: instance property of SockhopClient
Returns: boolean - compatibility_mode whether or not we are in compatibility mode
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
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)
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
Underlying net.socket
Kind: instance property of SockhopClient
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
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
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:
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:
Get bound address
Kind: instance method of SockhopClient
Returns: string - the IP address we are bound to
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 |
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 |
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) |
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 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 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 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 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 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 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 |
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 |
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 |
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) |
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 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 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 |
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
Constructs a new SockhopError
| Param | Type | Description |
|---|---|---|
| message | string |
A message string describing the error |
| code | string |
A standardized code for filtering error types |
TCP Ping
Used internally when .ping() is called
Kind: global class
Unanswered
Is this ping Unanswered?
Kind: instance method of SockhopPing
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 |
TCP Ping reply
Used internally when .ping() is replied
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
- SockhopServer ⇐
EventEmitter- new SockhopServer([opts])
- .sockets :
Array.<net.Socket> - .sessions :
Array.<SockhopSession> - .compatibility_mode ⇒
boolean - .debug ⇒
boolean - .emit_async()
- .ping(delay)
- .listen() ⇒
Promise.<net.server> - .get_bound_address() ⇒
string - .send(socket, object, [callback]) ⇒
Promise - .send_typed_buffer(socket, type, buff, [callback]) ⇒
Promise - .sendall(object) ⇒
Promise - .kill_socket(sock) ⇒
Promise - .disconnect() ⇒
Promise - .close() ⇒
Promise - "connect" (sock, session)
- "handshake" (sock, session, success, error)
- "receive" (object, meta)
- "receive:buffer" (buffer, meta)
- "disconnect" (sock, session, handshaked)
- "unhandshake" (sock, session)
- "debug:sending" (object, buffer, binary_mode, sock, session)
- "debug:received" (object, buffer, binary_mode, sock, session)
- "debug:sending:buffer" (object, buffer, binary_mode, sock, session)
- "debug:received:buffer" (object, buffer, binary_mode, sock, session)
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) |
Socket getter
Kind: instance property of SockhopServer
sockhopServer.sessions : Array.<SockhopSession>
Session getter
Kind: instance property of SockhopServer
compatibility_mode getter
Kind: instance property of SockhopServer
Returns: boolean - compatibility_mode whether or not we are in compatibility mode
debug mode getter
Kind: instance property of SockhopServer
Returns: boolean - debug whether or not we are in debug mode
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
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) |
Listen
Bind and wait for incoming connections
Kind: instance method of SockhopServer
Get bound address
Kind: instance method of SockhopServer
Returns: string - the IP address we are bound to
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 |
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 |
Sendall
Send an object to all clients
Kind: instance method of SockhopServer
| Param | Type | Description |
|---|---|---|
| object | object |
to send to all connected clients |
Stops a client connection
Kind: instance method of SockhopServer
| Param | Type | Description |
|---|---|---|
| sock | net.Socket |
the client socket to kill |
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
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 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 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 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 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 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 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 |
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 |
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 |
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 |
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 |
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
- SockhopSession ⇐
EventEmitter- new SockhopSession(sock, server)
- .sock :
net.Socket - .server :
SockhopServer - .init_complete ⇒
boolean - .binary_mode ⇒
object|boolean|boolean - .handshake_successful ⇒
boolean - .send_typed_buffer(type, buff, [callback]) ⇒
Promise - .send(obj, [callback]) ⇒
Promise - .kill() ⇒
Promise - .start() ⇒
Promise - .end() ⇒
Promise - "handshake" (success, error)
- "receive" (object, meta)
- "unhandshake"
- "disconnect" (handshaked)
- "debug:sending" (object, buffer, binary_mode)
- "debug:received" (object, buffer, binary_mode)
- "debug:sending:buffer" (object, buffer, binary_mode)
- "debug:received:buffer" (object, buffer, binary_mode)
- "receive:buffer" (buffer, meta)
- "binary_mode:rx" (enabled)
- "binary_mode:tx" (enabled)
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 |
Getter for the underlying session socket
Kind: instance property of SockhopSession
sockhopSession.server : SockhopServer
Getter for the server
Kind: instance property of SockhopSession
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)
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
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
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 |
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 |
Kill this session
Kind: instance method of SockhopSession
Returns: Promise - resolves on socket end
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
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 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 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 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 event
Kind: event emitted by SockhopSession
| Param | Type | Description |
|---|---|---|
| handshaked | boolean |
true if we were previously handshaked, false otherwise |
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 |
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 |
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) |
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 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 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 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 |