Package Exports
- anysocket
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (anysocket) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
AnySocket
An abstract networking layer over multiple transports, agnostic of client/server with support for E2EE*
** E2EE implementation doesn't support forward secrecy (atm)
Important
This is a work in progress and API is subject to change.
WIP Documentation
Features
- Client / Server agnostic
- Support for request/reply
- P2P using a proxy server (with support for E2EE between clients)
- Browser support - small footprint (24kb) - see:
/dist/anysocket.bundle.js - Multiple transports *(implemented: ws)
- All peers have a UUIDv4 associated
- E2EE implemented in the protocol
- Disconnect detection using a heartbeat
- Automatic packet splitting, if packet is too large (atm: fixed 4kb packet size)
- Not Battle Tested ...yet
It doesn't support Binary Protocol... (but it has some binary stuff)
Benchmark
nodejs - browser
Running PLAIN TEXT benchmark: 1000ms (test duration)
Latency: 0.90 ms
Running E2EE benchmark: 1000ms (test duration)
Latency: 2.81 msnodejs - nodejs
Running PLAIN TEXT benchmark: 1000ms (test duration)
Latency: 0.4 ms
Running E2EE benchmark: 1000ms (test duration)
Latency: 2.07 msYou can run the benchmarks from: /examples/benchmark
Installation
npm install --save anysocketor
<script src="/dist/anysocket.bundle.js"></script>How to use
The following example starts a websocket server on port 3000.
const AnySocket = require("anysocket");
const server = new AnySocket();
const PORT = 3000;
server.listen("ws", PORT)
.then(() => {
console.log("Listening on port:", PORT);
})
.catch((err) => {
console.error("Failed to start server:", err);
});
server.on("connected", (peer) => {
console.log("Connected", peer.id);
peer.send({
hello: "world"
});
});
server.on("message", (packet) => {
console.log("From:", packet.peer.id, "Message:", packet.msg);
});
server.on("disconnected", (peer, reason) => {
console.log("Disconnected", peer.id, "Reason:", reason);
});The following example connects to a websocket on port 3000
const AnySocket = require("anysocket");
const client = new AnySocket();
const PORT = 3000;
client.connect("ws", "127.0.0.1", PORT)
.then(() => {
// note: you cannot send messages from here, you need to wait for the "connected" event
console.log("Connected to server");
})
.catch((err) => {
console.error("Failed to connect to server:", err);
});
// after negotiating the AUTH packet, it will trigger the connect event
client.on("connected", (peer) => {
console.log("Connected", peer.id);
peer.send({
hello: "world"
});
});
client.on("message", (packet) => {
console.log("From:", packet.peer.id, "Message:", packet.msg);
});
client.on("disconnected", (peer, reason) => {
console.log("Disconnected", peer.id, "Reason:", reason);
});More in the examples folder.
Api
AnySocket()AnyPacket()AnyPeer()idlagconnectionIDe2e()send()disconnect()heartbeat()- deprecated, will be movedisProxy()isE2EEnabled()event: messageevent: e2eevent: heartbeatevent: disconnected
Documentation
AnySocket()
Creates a new AnySocket instance
AnySocket.id
Unique identifier (UUIDv4) that will be used for all connections originating this instance (client/server)
AnySocket.server(scheme, options)
Alias for AnySocket.listen()
AnySocket.listen(scheme, options)
Attaches a new server transport based on the selected *scheme
Arguments:
scheme- one of the implemented transportsoptions- one of the options belowport- port numberjson
{
ip: "0.0.0.0", // listening ip
port: 3000, // listening port
replyTimeout: 30 * 1000, // reply timeout
heartbeatInterval: 5 * 1000, // heartbeat interval
heartbeatTimeout: 5 * 1000 // heartbeat timeout (disconnect)
}Returns a Promise that resolves/rejects when the server has started listening or when it throws an error
AnySocket.connect(scheme, ip, port, [options])
Connects to AnySocket Server
Arguments:
scheme- one of the implemented transportsip- server ipport- server portoptions- options json
{
replyTimeout: 30 * 1000, // reply timeout
heartbeatInterval: 5 * 1000, // heartbeat interval
heartbeatTimeout: 5 * 1000 // heartbeat timeout (disconnect)
}Returns a Promise that resolves/rejects when a connection has been established
note: you cannot take actions (ex: send) until the connected event has been triggered
AnySocket.stop()
Stops all servers and disconnects all peers
Returns a Promise that resolves/rejects when finished
AnySocket.send(message, awaitReply)
Sends a message to all connected peers
Arguments:
message- a JSON stringifiable objectawaitReply- set to true if a reply is expected
Returns a Promise that resolves with a AnyPacket if waiting for a reply or rejects on error
note: it doesn't resolve if awaitReply is not set
AnySocket.canProxy(peerID, otherPeerID)
Checks if peerID can be proxied through otherPeerID. Defaults to: false
note: You need to override this function in order to allow proxying
Returns true/false
AnySocket.hasPeer(id)
note: returns true for proxies
Returns true/false if AnySocket has a peer with the id
AnySocket.hasDirectPeer(id)
note: returns false for proxies
Returns true/false if AnySocket has a direct peer (no proxy) with the id
AnySocket.proxy(peerID, throughPeerID)
Send a proxy request for peerID via throughPeerID as relay
note: A proxied peer uses the same flow as a new connection
Returns a Promise that resolves with a AnyPeer or rejects if proxy fails
AnySocket event connected
Emitted when the link has been established and it's ready for sending/receiving messages
Arguments:
peer- AnyPeer instance
AnySocket event message
Emitted when a message is received
Arguments:
packet- AnyPacket instance
AnySocket event e2e
Emitted when the link has been end-to-end encrypted and it's ready to be used
Arguments:
peer- AnyPeer instance
AnySocket event heartbeat
Emitted when a PING/PONG heartbeat has finished
Arguments:
peer- AnyPeer instance
AnySocket event disconnected
Emitted when a peer has disconnected
Arguments:
peer- AnyPeer instancereason- a string detailing the disconnect reason
AnyPacket()
Constructor should not be used directly
AnyPacket.seq
An incremental unique identifier per packet per peer (used internally)
AnyPacket.peer
An AnyPeer instance
AnyPacket.msg
An object that contains data sent/received from a peer
AnyPacket.reply(message)
Sends a reply to the current packet
Arguments:
message- a JSON stringifiable object
note: you can only reply to a normal message, you cannot reply to a reply packet. It fails silently
AnyPeer()
Constructor should not be used directly
AnyPeer.id
Unique peer identifier (UUIDv4) - Peer AnySocket.id
AnyPeer.lag
Last calculated latency (based on heartbeat) in milliseconds
AnyPeer.connectionID
Unique connection identifier (UUIDv4), used internally before getting a AnyPeer.id
AnyPeer.e2e()
Enables E2E encryption. The certificate is generated on the spot with a size of 4096 bytes
AnyPeer.send(message, [awaitReply, [timeout]])
Sends a message to the peer
Arguments:
message- a JSON stringifiable objectawaitReply- set to true if a reply is expectedtimeout- set a custom reply packet timeout (in milliseconds)
Returns a Promise that resolves with a AnyPacket if waiting for a reply or rejects on error
note: it doesn't resolve if awaitReply is not set
note: you can only reply to a normal message, you cannot reply to a reply packet. It fails silently
AnyPeer.disconnect(reason)
Disconnects the peer
Arguments:
reason- a string that explains why the peer was disconnected
AnyPeer.heartbeat()
Send a heartbeet to the peer - used internally
AnyPeer.isProxy()
Returns true if the AnyPeer instance is a proxy (see: AnySocket.proxy)
AnyPeer.isE2EEnabled()
Returns true if the connection has been end-to-end encrypted (see: AnyPeer.e2e)
AnyPeer event message
Emitted when a message is received
Arguments:
packet- AnyPacket instance
AnyPeer event e2e
Emitted when the link has been end-to-end encrypted and it's ready to be used
Arguments:
peer- AnyPeer instance
AnyPeer event heartbeat
Emitted when a PING/PONG heartbeat has finished
Arguments:
peer- AnyPeer instance
AnyPeer event disconnected
Emitted when the peer has disconnected
Arguments:
peer- AnyPeer instancereason- a string detailing the disconnect reason
Upcoming Features
- Mesh Network
- Multiple transports: wss, tcp, http, udp*, ipc
- RPC support
- Client reconnection
- Custom AUTH method
* this will require a change in the protocol, as the protocol assumes the packets are sent using a reliable, ordered connection
License
MIT