|
| 1 | +[](https://travis-ci.org/tcp-emitter/server) |
| 2 | + |
| 3 | +# TCP Emitter Server |
| 4 | + |
| 5 | +`TCP Emitter Server` is a [net.Server](https://nodejs.org/api/net.html#net_class_net_server) object that acts as an [Event Emitter](https://nodejs.org/api/events.html#events_class_eventemitter) router for different processes. These processes (known as `TCP Emitter clients`) can be implemented in any language and interact with `TCP Emitter server` via the [TCP Protocol](https://tools.ietf.org/html/rfc793). |
| 6 | + |
| 7 | +# Installation |
| 8 | + |
| 9 | +``` |
| 10 | +npm install --save tcp-emitter |
| 11 | +``` |
| 12 | + |
| 13 | +# API |
| 14 | +## require('tcp-emitter')(options) |
| 15 | + |
| 16 | +Options | Type | Default | Description |
| 17 | +---------------------- | ---------- | ------------ | ----------- |
| 18 | +`options.delimiter` | `string` | '@@@' | Delimiter used to seperate payloads in a single TCP request. [More info here](#delimiter). |
| 19 | +`options.verifyClient` | `function` | `() => true` | Function used to determine whether to allow or deny a `TCP Emitter client` connection. By default all connections are allowed. [More info here](#verify-client). |
| 20 | + |
| 21 | +### Delimiter |
| 22 | +Delimiter used to seperate payloads in a single TCP request. Apart from making it possible for `TCP Emitter clients` to combine multiple payloads in a single TCP request, this was mainly implemented due to the use of [Nagle's algorithm](https://en.wikipedia.org/wiki/Nagle%27s_algorithm) in NodeJS [net](https://nodejs.org/api/net.html) module. When sending data through TCP while using `net` module in seperate [.write()](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback) invocations, it will try to combine the messages together and send them in a single TCP request. For this reason when sending a payload (even when a TCP message consist of one payload), it should end with the specified delimiter. |
| 23 | + |
| 24 | +#### Nagle's algorithm in NodeJS |
| 25 | +```javascript |
| 26 | +// Sending a message from the client side. |
| 27 | +clientSocket.write('hello') |
| 28 | +clientSocket.write('world') |
| 29 | + |
| 30 | +// Receiving the message from the server side. |
| 31 | +serverSocket.on('data', console.log) // => 'helloworld' |
| 32 | +``` |
| 33 | + |
| 34 | +### Verify Client |
| 35 | +Function used to verify whether a connection should be allowed or denied. When omitted, all connections are allowed. When specified a connection will be allowed if it returns `true`. When this function requires async processing it should return a `Promise` resolved with `true` to allow a connection or any other value but `true` to deny it. |
| 36 | + |
| 37 | +### Synchronous Verify Client. |
| 38 | +```javascript |
| 39 | +const verifyClient = socket => allowed.indexOf(socket.address().address) !== -1 |
| 40 | +require('tcpEmitter')(verifyClient).listen({ host: 'localhost', port: 8080 }) |
| 41 | +``` |
| 42 | + |
| 43 | +### Asynchronous Verify Client |
| 44 | +```javascript |
| 45 | +const verifyClient = socket => { |
| 46 | + return makeRequest('GET', '/allowed').then(allowed => { |
| 47 | + return allowed.indexOf(socket.address().address) !== -1 |
| 48 | + }) |
| 49 | +} |
| 50 | + |
| 51 | +require('tcpEmitter')(verifyClient).listen({ host: 'localhost', port: 8080 }) |
| 52 | +``` |
| 53 | + |
| 54 | +# TCP Emitter Clients |
| 55 | +As specified in the introduction, these can be implemented in any language as long as they follow the TCP Emitter Payload spec. A TCP Emitter client can do the following three different interactions with the `TCP Emitter server`: |
| 56 | + |
| 57 | +> Examples assume that '@@@' delimiter is used. For more info about why delimiter is used please [refer to this section](#delimiter). |
| 58 | +
|
| 59 | +Name | Description |
| 60 | +----------- | ------------------------------------------------------------------------------- |
| 61 | +subscribe | Subscribe (Listen) to an event. |
| 62 | +unsubscribe | Unsubscribe from an event. |
| 63 | +broadcast | Broadcast (notify) the listeners (i.e. other `TCP Emitter clients`) of an event. |
| 64 | + |
| 65 | +## Payload Spec |
| 66 | + |
| 67 | +### Subscribe |
| 68 | +Attribute | Type | Description |
| 69 | +--------- | -------- | -------------------- |
| 70 | +`type` | `string` | Type of interaction, for a subscription this should be set to `subscribe`. |
| 71 | +`event` | `string` | Name of event to subscribe to. |
| 72 | + |
| 73 | +### Example |
| 74 | +``` json |
| 75 | +{"type": "subscribe", "event": "event-name"}@@@ |
| 76 | +``` |
| 77 | + |
| 78 | +### Unsubscribe |
| 79 | +Attribute | Type | Description |
| 80 | +--------- | -------- | -------------------- |
| 81 | +`type` | `string` | Type of interaction, for an unsubscription this should be set to `unsubscribe`. |
| 82 | +`event` | `string` | Name of event to unsubscribe from. |
| 83 | + |
| 84 | +### Example |
| 85 | +``` json |
| 86 | +{"type": "unsubscribe", "event": "event-name"}@@@ |
| 87 | +``` |
| 88 | + |
| 89 | +### Broadcast |
| 90 | +Attribute | Type | Description |
| 91 | +--------- | ------------- | -------------------- |
| 92 | +`type` | `string` | Type of interaction, for a broadcast this should be set to `broadcast`. |
| 93 | +`event` | `string` | Name of event to broadcast to. |
| 94 | +`args` | `Array.<any>` | Arguments that will be broadcasted to the TCP Emitter clients with the event. |
| 95 | + |
| 96 | +> When a TCP Emitter client broadcasts to an event which itself is subscribed to, it won't be notified by TCP Emitter server. |
| 97 | +
|
| 98 | +### Example |
| 99 | +``` json |
| 100 | +{"type": "broadcast", "event": "event-name", "args": [1, "text", true, {"name": "luca"}]}@@@ |
| 101 | +``` |
| 102 | + |
| 103 | +## Multi-Payload TCP Request |
| 104 | +As mentioned in the delimiter section, TCP Emitter clients can send multiple payloads in a single TCP Request. The following is an example of a TCP Request message containing multiple payloads. |
| 105 | + |
| 106 | +```json |
| 107 | +{"type": "subscribe", "event": "new-user"}@@@{"type": "unsubscribe", "event": "new-admin"}@@@{"type": "broadcast", "event": "access-change", "args": ["user"]}@@@ |
| 108 | +``` |
| 109 | + |
| 110 | +# Example |
| 111 | +TCP Emitter server configured with a delimiter set to `!!!` |
| 112 | +```javascript |
| 113 | +require('tcp-emitter')({ |
| 114 | + delimiter: '!!!' |
| 115 | +}).listen({ host: 'localhost', port: 8080 }) |
| 116 | +``` |
| 117 | + |
| 118 | +> Note in this example `TCP Emitter clients` are implemented in JavaScript, however as mentioned in the introduction these can be implemented in any language. |
| 119 | +
|
| 120 | +TCP Emitter client 1. |
| 121 | +```javascript |
| 122 | +const clientOne = require('net').createConnection({ |
| 123 | + host: 'localhost', |
| 124 | + port: 8080 |
| 125 | +}, () => { |
| 126 | + clientOne.on('data', console.log) |
| 127 | + |
| 128 | + clientOne.setEncoding('utf-8') |
| 129 | + |
| 130 | + clientOne.write(JSON.stringify({ |
| 131 | + type: 'subscribe', |
| 132 | + event: 'got-episode' |
| 133 | + }) + '!!!') |
| 134 | +}) |
| 135 | +``` |
| 136 | + |
| 137 | +TCP Emitter client 2. |
| 138 | +```javascript |
| 139 | +const clientTwo = require('net').createConnection({ |
| 140 | + host: 'localhost', |
| 141 | + port: 8080 |
| 142 | +}, () => { |
| 143 | + clientTwo.on('data', console.log) |
| 144 | + |
| 145 | + clientTwo.setEncoding('utf-8') |
| 146 | + |
| 147 | + clientTwo.write(JSON.stringify({ |
| 148 | + type: 'subscribe', |
| 149 | + event: 'got-episode' |
| 150 | + }) + '!!!') |
| 151 | +}) |
| 152 | +``` |
| 153 | + |
| 154 | +When TCP Emitter 1 broadcasts to `got-episode` event: |
| 155 | + |
| 156 | +```javascript |
| 157 | +clientOne.write(JSON.stringify({ |
| 158 | + type: 'broadcast', |
| 159 | + event: 'got-episode', |
| 160 | + args: ['S7E5 - Eastwatch'] |
| 161 | +}) + '!!!') |
| 162 | +``` |
| 163 | + |
| 164 | +TCP Emitter 2 'data' listener will be invoked with the following string: |
| 165 | +```javascript |
| 166 | +'{"event":"got-episode","args":["S7E5 - Eastwatch"]}!!!' |
| 167 | +``` |
| 168 | + |
| 169 | +# Tests |
| 170 | +``` |
| 171 | +npm install |
| 172 | +npm test |
| 173 | +``` |
| 174 | + |
| 175 | +# Generate Documentation |
| 176 | +``` |
| 177 | +npm install |
| 178 | +npm run docs |
| 179 | +``` |
| 180 | + |
| 181 | +# License |
| 182 | +ISC |
0 commit comments