├── LICENSE ├── limiting_concurrency ├── server_limit_client.js ├── server_limit_incoming.js └── server_nolimit.js ├── queues ├── array.js ├── array_offset.js └── test.js └── udp ├── chat-client.js ├── chat-server.js ├── hello-client.js ├── hello-server.js └── tftp.js /LICENSE: -------------------------------------------------------------------------------- 1 | Public Domain Certification 2 | 3 | Copyright-Only Dedication (based on United States law) or Public Domain 4 | Certification 5 | 6 | The person or persons who have associated work with this document (the 7 | "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of 8 | his knowledge, the work of authorship identified is in the public domain of the 9 | country from which the work is published, or (b) hereby dedicates whatever 10 | copyright the dedicators holds in the work of authorship identified below (the 11 | "Work") to the public domain. A certifier, moreover, dedicates any copyright 12 | interest he may have in the associated work, and for these purposes, is 13 | described as a "dedicator" below. 14 | 15 | A certifier has taken reasonable steps to verify the copyright status of this 16 | work. Certifier recognizes that his good faith efforts may not shield him from 17 | liability if in fact the work certified is not in the public domain. 18 | 19 | Dedicator makes this dedication for the benefit of the public at large and to 20 | the detriment of the Dedicator's heirs and successors. Dedicator intends this 21 | dedication to be an overt act of relinquishment in perpetuity of all present 22 | and future rights under copyright law, whether vested or contingent, in the 23 | Work. Dedicator understands that such relinquishment of all rights includes the 24 | relinquishment of all rights to enforce (by lawsuit or otherwise) those 25 | copyrights in the Work. 26 | 27 | Dedicator recognizes that, once placed in the public domain, the Work may be 28 | freely reproduced, distributed, transmitted, used, modified, built upon, or 29 | otherwise exploited by anyone for any purpose, commercial or non-commercial, 30 | and in any way, including by methods that have not yet been invented or 31 | conceived. -------------------------------------------------------------------------------- /limiting_concurrency/server_limit_client.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 3 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 4 | * LICENSE file. 5 | */ 6 | 7 | var http = require('http'); 8 | var sys = require('sys'); 9 | var destination = "nodejs.org"; 10 | 11 | var maxClients = 1; 12 | var currentClients = 0; 13 | var _pending = []; 14 | 15 | function process_pending() 16 | { 17 | if (_pending.length > 0) { 18 | var cb = _pending.shift(); 19 | currentClients++; 20 | cb(function() { 21 | currentClients--; 22 | process.nextTick(process_pending); 23 | }); 24 | } 25 | } 26 | 27 | function client_limit(cb, req, res) 28 | { 29 | if (currentClients < maxClients) { 30 | currentClients++; 31 | cb(function() { 32 | currentClients--; 33 | process.nextTick(process_pending); 34 | }, req, res); 35 | } 36 | else { 37 | console.log('Overloaded, queuing clients...'); 38 | _pending.push(cb); 39 | } 40 | } 41 | 42 | http.createServer(function(req, res) { 43 | var bufs = []; 44 | var done_buffering = false; 45 | 46 | client_limit(function(done){ 47 | var proxy = http.createClient(80, destination); 48 | var preq = proxy.request(req.method, req.url, req.headers); 49 | 50 | console.log(req.connection.remoteAddress +" "+ req.method +" "+req.url); 51 | preq.on('response', function(pres) { 52 | res.writeHead(pres.statusCode, pres.headers); 53 | sys.pump(pres, res); 54 | pres.on('end', function() { 55 | preq.end(); 56 | res.end(); 57 | done(); 58 | }); 59 | }); 60 | 61 | function finishreq() { 62 | bufs.forEach(function(buf){ 63 | preq.write(buf); 64 | }); 65 | preq.end(); 66 | } 67 | 68 | if (done_buffering) { 69 | finishreq(); 70 | } 71 | else { 72 | req.on('end', function() { 73 | finishreq(); 74 | }); 75 | } 76 | }); 77 | 78 | req.on('data', function(chunk) { 79 | var tbuf = new Buffer(chunk.length); 80 | chunk.copy(tbuf, 0, 0); 81 | bufs.push(tbuf); 82 | }); 83 | 84 | req.on('end', function() { 85 | done_buffering = true; 86 | }); 87 | 88 | }).listen(8080); 89 | -------------------------------------------------------------------------------- /limiting_concurrency/server_limit_incoming.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 3 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 4 | * LICENSE file. 5 | */ 6 | 7 | var http = require('http'); 8 | var sys = require('sys'); 9 | var destination = "nodejs.org"; 10 | var port = 8080; 11 | var maxClients = 2; 12 | var currentClients = 0; 13 | var active = true; 14 | 15 | var hs = null; 16 | 17 | function activate() { 18 | if (!active && currentClients < maxClients) { 19 | hs.watcher.start(); 20 | active = true; 21 | } 22 | } 23 | 24 | hs = http.createServer(function(req, res) { 25 | var proxy = http.createClient(80, destination); 26 | var preq = proxy.request(req.method, req.url, req.headers); 27 | 28 | console.log(req.connection.remoteAddress +" "+ req.method +" "+req.url); 29 | preq.on('response', function(pres) { 30 | res.writeHead(pres.statusCode, pres.headers); 31 | sys.pump(pres, res); 32 | pres.on('end', function() { 33 | preq.end(); 34 | res.end(); 35 | currentClients--; 36 | activate(); 37 | }); 38 | }); 39 | req.on('data', function(chunk) { 40 | preq.write(chunk, 'binary'); 41 | }); 42 | req.on('end', function() { 43 | preq.end(); 44 | }); 45 | 46 | currentClients++; 47 | if (currentClients >= maxClients) { 48 | hs.watcher.stop(); 49 | active = false; 50 | } 51 | }); 52 | 53 | hs.listen(port); 54 | 55 | -------------------------------------------------------------------------------- /limiting_concurrency/server_nolimit.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 3 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 4 | * LICENSE file. 5 | */ 6 | 7 | var http = require('http'); 8 | var sys = require('sys'); 9 | var destination = "nodejs.org"; 10 | 11 | http.createServer(function(req, res) { 12 | var proxy = http.createClient(80, destination); 13 | var preq = proxy.request(req.method, req.url, req.headers); 14 | 15 | console.log(req.connection.remoteAddress +" "+ req.method +" "+req.url); 16 | preq.on('response', function(pres) { 17 | res.writeHead(pres.statusCode, pres.headers); 18 | sys.pump(pres, res); 19 | pres.on('end', function() { 20 | preq.end(); 21 | res.end(); 22 | }); 23 | }); 24 | req.on('data', function(chunk) { 25 | preq.write(chunk, 'binary'); 26 | }); 27 | req.on('end', function() { 28 | preq.end(); 29 | }); 30 | }).listen(8080); 31 | -------------------------------------------------------------------------------- /queues/array.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | function ArrayQueue() 7 | { 8 | this.q = []; 9 | } 10 | 11 | ArrayQueue.prototype.clear = function() 12 | { 13 | this.q = []; 14 | } 15 | 16 | ArrayQueue.prototype.insert = function(value) 17 | { 18 | this.q.push(value); 19 | } 20 | 21 | ArrayQueue.prototype.shift = function() 22 | { 23 | if (this.q.length != 0) { 24 | return this.q.shift(); 25 | } 26 | else { 27 | return null; 28 | } 29 | } 30 | 31 | exports.createQueue = function() 32 | { 33 | return new ArrayQueue(); 34 | } -------------------------------------------------------------------------------- /queues/array_offset.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | function ArrayOffsetQueue() 7 | { 8 | this.offset = 0; 9 | this.head = []; 10 | this.tail = []; 11 | } 12 | 13 | ArrayOffsetQueue.prototype.clear = function() 14 | { 15 | this.offset = 0; 16 | this.head = []; 17 | this.tail = []; 18 | } 19 | 20 | ArrayOffsetQueue.prototype.insert = function(value) 21 | { 22 | this.tail.push(value); 23 | } 24 | 25 | ArrayOffsetQueue.prototype.shift = function() 26 | { 27 | if (this.offset === this.head.length) { 28 | var tmp = this.head; 29 | this.head = this.tail; 30 | this.tail = tmp; 31 | this.tail.length = 0; 32 | this.offset = 0; 33 | if (this.head.length === 0) { 34 | return null; 35 | } 36 | } 37 | return this.head[this.offset++]; 38 | } 39 | 40 | exports.createQueue = function() 41 | { 42 | return new ArrayOffsetQueue(); 43 | } -------------------------------------------------------------------------------- /queues/test.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var assert = require('assert'); 7 | 8 | var queues = { 9 | 'array': require('./array'), 10 | 'array_offset': require('./array_offset') 11 | }; 12 | 13 | function DummyObject(value) 14 | { 15 | this.foo = value; 16 | } 17 | 18 | DummyObject.prototype.some_method = function() 19 | { 20 | return this.foo; 21 | } 22 | 23 | function benchmark_run(q, pull_size, insert_size, total_size) 24 | { 25 | var i = 0; 26 | var j, v; 27 | 28 | while (i < total_size) { 29 | for (j = 0; j < insert_size && i < total_size; j++, i++) { 30 | q.insert(new DummyObject(i)); 31 | } 32 | for (j = 0; j < pull_size; j++) { 33 | v = q.shift(); 34 | if (v !== null) { 35 | delete v; 36 | } 37 | } 38 | } 39 | 40 | while (true) { 41 | v = q.shift(); 42 | if (v === null) { 43 | break; 44 | } 45 | delete v; 46 | }; 47 | } 48 | 49 | function benchmark_method(m) 50 | { 51 | var maxsize = 100000; 52 | var start = process.memoryUsage(); 53 | var q = m.createQueue(); 54 | benchmark_run(q, 1, 10, maxsize); 55 | q.clear(); 56 | benchmark_run(q, 10, 10, maxsize); 57 | q.clear(); 58 | benchmark_run(q, 10, 1000, maxsize); 59 | q.clear(); 60 | benchmark_run(q, 10, 1, maxsize); 61 | q.clear(); 62 | benchmark_run(q, 100, 1, maxsize); 63 | q.clear(); 64 | var end = process.memoryUsage(); 65 | delete q; 66 | return [start, end]; 67 | } 68 | 69 | for (k in queues) { 70 | var m = queues[k]; 71 | var start = Date.now(); 72 | mem = benchmark_method(m); 73 | var end = Date.now(); 74 | delete q; 75 | console.log(k, "took", end-start, 'ms', 'heapdiff:', mem[0].heapUsed - mem[1].heapUsed); 76 | console.log() 77 | } -------------------------------------------------------------------------------- /udp/chat-client.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var Buffer = require('buffer').Buffer; 7 | var dgram = require('dgram'); 8 | 9 | var stdin = process.openStdin(); 10 | stdin.setEncoding('utf8'); 11 | 12 | SERVER_HOST = '127.0.0.1'; 13 | SERVER_PORT = 7000; 14 | 15 | var sock = dgram.createSocket("udp4"); 16 | 17 | stdin.on('data', function (input) { 18 | var buf = new Buffer(input); 19 | sock.send(buf, 0, buf.length, SERVER_PORT, SERVER_HOST); 20 | }); 21 | 22 | sock.on('message', function (buf) { 23 | process.stdout.write(buf.toString()); 24 | }); 25 | -------------------------------------------------------------------------------- /udp/chat-server.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var Buffer = require('buffer').Buffer; 7 | var dgram = require('dgram'); 8 | var log = require('sys').log; 9 | var CLIENT_GENERATION_GAP = 10; 10 | var CLIENT_CLEANER_INTERVAL = 1000; 11 | SERVER_HOST = '0.0.0.0'; 12 | SERVER_PORT = 7000; 13 | 14 | function ts() { 15 | return Math.round(new Date().getTime() / 1000); 16 | } 17 | 18 | var clients = {}; 19 | var httpclients = []; 20 | var generation = ts(); 21 | var sock = null; 22 | 23 | var si = setInterval(function() { 24 | generation = ts(); 25 | for (var ckey in clients) { 26 | if (clients.hasOwnProperty(ckey)) { 27 | var gap = generation - clients[ckey]; 28 | /* No ping from this client in X seconds, assume its dead. */ 29 | if (gap > CLIENT_GENERATION_GAP) { 30 | delete clients[ckey]; 31 | } 32 | } 33 | } 34 | }, CLIENT_CLEANER_INTERVAL); 35 | 36 | function updateTimeout(key) { 37 | clients[key] = generation; 38 | } 39 | 40 | function broadcast(buf) { 41 | var c = 0; 42 | for (var ckey in clients) { 43 | if (clients.hasOwnProperty(ckey)) { 44 | var host = ckey.slice(0, ckey.lastIndexOf(':')); 45 | var port = parseInt(ckey.slice(ckey.lastIndexOf(':')+1), 10); 46 | c++; 47 | sock.send(buf, 0, buf.length, port, host); 48 | } 49 | } 50 | log('Broadcasted to '+ c + ' UDP clients'); 51 | 52 | var dead = []; 53 | for (var i = 0; i < httpclients.length; i++) { 54 | if (httpclients[i].connection.writable) { 55 | httpclients[i].write(buf); 56 | } 57 | else { 58 | dead.push(httpclients[i]); 59 | } 60 | } 61 | 62 | httpclients = httpclients.filter(function(r) { 63 | return dead.indexOf(r) === -1; 64 | }); 65 | 66 | log('Broadcasted to '+ httpclients.length + ' HTTP clients'); 67 | } 68 | 69 | function processMsg(msg, peer) { 70 | var str = msg.toString(); 71 | str = str.replace(/[\n\r]/g, ""); 72 | if (str.length > 0) { 73 | var buf = new Buffer(peer.address + ":"+ peer.port + "> "+ str + '\n'); 74 | broadcast(buf); 75 | } 76 | } 77 | 78 | sock = dgram.createSocket("udp4", function (msg, peer) { 79 | var key = peer.address + ":" + peer.port; 80 | updateTimeout(key); 81 | processMsg(msg, peer); 82 | }); 83 | 84 | sock.on('listening', function() { 85 | log('Bound to '+ SERVER_HOST + ':' + SERVER_PORT); 86 | }); 87 | sock.bind(SERVER_PORT, SERVER_HOST); 88 | 89 | 90 | var http = require('http'); 91 | http.createServer(function (request, response) { 92 | response.writeHead(200, {'Content-Type': 'text/plain'}); 93 | response.write('\n'); 94 | httpclients.push(response); 95 | }).listen(SERVER_PORT, SERVER_HOST); 96 | -------------------------------------------------------------------------------- /udp/hello-client.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var Buffer = require('buffer').Buffer; 7 | var dgram = require('dgram'); 8 | 9 | var sock = dgram.createSocket("udp4"); 10 | 11 | var buf = new Buffer("hello world"); 12 | 13 | sock.send(buf, 0, buf.length, 8000, "127.0.0.1"); 14 | sock.close(); 15 | -------------------------------------------------------------------------------- /udp/hello-server.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var Buffer = require('buffer').Buffer; 7 | var dgram = require('dgram'); 8 | var log = require('sys').log; 9 | 10 | sock = dgram.createSocket("udp4", function (msg, rinfo) { 11 | log('got message from '+ rinfo.address +':'+ rinfo.port); 12 | log('data len: '+ rinfo.size + " data: "+ msg.toString('ascii', 0, rinfo.size)); 13 | sock.close(); 14 | }); 15 | 16 | sock.bind(8000, '0.0.0.0'); -------------------------------------------------------------------------------- /udp/tftp.js: -------------------------------------------------------------------------------- 1 | /* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, 2 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying 3 | * LICENSE file. 4 | */ 5 | 6 | var dgram = require('dgram'); 7 | var slog = require('sys').log; 8 | var fs = require('fs'); 9 | 10 | var SERVER_HOST='127.0.0.1'; 11 | var SERVER_PORT=1069; 12 | 13 | 14 | var opcodes = {OPCODE_RRQ: 1, 15 | OPCODE_WRQ: 2, 16 | OPCODE_DATA: 3, 17 | OPCODE_ACK: 4, 18 | OPCODE_ERROR: 5}; 19 | 20 | var sessions = {}; 21 | var sock = null; 22 | 23 | function log(peer, msg) { 24 | slog("[" + peer.address + ":" + peer.port + "] "+ msg); 25 | } 26 | 27 | function decodeOp(msg, peer) { 28 | if (msg.length < 4) { 29 | log(peer, 'Message too short to be valid.'); 30 | return null; 31 | } 32 | 33 | if (msg[0] !== 0) { 34 | log(peer, 'Invalid Opcode, no leading zero.'); 35 | return null; 36 | } 37 | 38 | var b = msg[1]; 39 | 40 | for (var op in opcodes) { 41 | if (opcodes.hasOwnProperty(op)) { 42 | if (b == opcodes[op]) { 43 | return op; 44 | } 45 | } 46 | } 47 | 48 | log(peer, 'Invalid Opcode, no such opcode '+ b); 49 | return null; 50 | } 51 | 52 | function clearSession(peer) { 53 | var key = peer.address + ":" + peer.port; 54 | delete sessions[key]; 55 | } 56 | 57 | function startSession(peer, file) { 58 | var key = peer.address + ":" + peer.port; 59 | sessions[key] = {'peer': peer, 'file': file}; 60 | sendBlock(peer, file, 1); 61 | } 62 | 63 | function continueSession(peer, block) { 64 | var key = peer.address + ":" + peer.port; 65 | var s = sessions[key]; 66 | if (s !== undefined) { 67 | sendBlock(peer, s.file, block); 68 | } 69 | else { 70 | log(peer, 'Ack for unknown session'); 71 | } 72 | } 73 | 74 | var ERR_UNDEFINED = 0; /* Not defined, see error message (if any). */ 75 | var ERR_FILE_NOT_FOUND = 1; /* File not found. */ 76 | var ERR_ACCESS_VIOLATION = 2; /* Access violation. */ 77 | var ERR_DISK_FULL = 3; /* Disk full or allocation exceeded. */ 78 | var ERR_ILLEGAL_OPERATION = 4; /* Illegal TFTP operation. */ 79 | var ERR_UNKNOWN_TRANSFER = 5; /* Unknown transfer ID. */ 80 | var ERR_FILE_EXISTS = 6; /* File already exists. */ 81 | var ERR_NO_SUCH_USER = 7; /* No such user. */ 82 | 83 | function sendError(peer, errorcode, msg) { 84 | clearSession(peer); 85 | if (msg === undefined) { 86 | msg = ""; 87 | } 88 | var buf = new Buffer(6 + msg.length); 89 | buf[0] = 0; 90 | buf[1] = opcodes.OPCODE_ERROR; 91 | buf[2] = 0; 92 | buf[3] = errorcode; 93 | buf.write(msg, 4); 94 | buf[4 + msg.length] = 0; 95 | sock.send(buf, 0, buf.length, peer.port, peer.address); 96 | } 97 | 98 | function getString(buf) { 99 | var slen; 100 | for (slen = 0; slen < buf.length; slen++) { 101 | if (buf[slen] === 0) { 102 | break; 103 | } 104 | } 105 | 106 | return [slen, buf.toString('ascii', 0, slen)]; 107 | } 108 | 109 | function sendBlock(peer, file, block) { 110 | log(peer, 'Sending block '+ block + " of "+ file); 111 | 112 | fs.open(file, 'r', function(err, fp) { 113 | if (err) { 114 | log(peer, "Error opening file: "+ err); 115 | sendError(peer, ERR_FILE_NOT_FOUND, "Can't open file: "+ file); 116 | return; 117 | } 118 | var buf = new Buffer(4 + 512); 119 | fs.read(fp, buf, 4, 512, ( block - 1 ) * 512, function(err, bytesRead) { 120 | if (err) { 121 | log(peer, "Error reading file: "+ err); 122 | sendError(peer, ERR_UNDEFINED, err); 123 | return; 124 | } 125 | buf[0] = 0; 126 | buf[1] = opcodes.OPCODE_DATA; 127 | buf[2] = (block >> 8) & 0xFF; 128 | buf[3] = block & 0xFF; 129 | sock.send(buf, 0, 4 + bytesRead, peer.port, peer.address); 130 | fs.close(fp); 131 | }); 132 | }); 133 | } 134 | 135 | sock = dgram.createSocket("udp4", function (msg, peer) { 136 | var key = peer.address + ":" + peer.port; 137 | var op = decodeOp(msg, peer); 138 | var buf = null; 139 | 140 | if (op === null) { 141 | sendError(peer, ERR_UNDEFINED, 'Unable to decode opcode'); 142 | return; 143 | } 144 | 145 | log(peer, 'OP '+ op); 146 | switch (op) { 147 | case "OPCODE_RRQ": 148 | buf = msg.slice(2); 149 | var tmp = getString(buf); 150 | buf = buf.slice(tmp[0]+1); 151 | 152 | var filename = tmp[1]; 153 | tmp = getString(buf); 154 | var mode = tmp[1]; 155 | log(peer, "requested file: "+ filename); 156 | log(peer, "mode: "+ mode); 157 | fs.stat(filename, function (err, stats) { 158 | if (!err && stats.isFile()) { 159 | startSession(peer, filename); 160 | } 161 | else { 162 | sendError(peer, ERR_FILE_NOT_FOUND, "not a file: "+ filename); 163 | } 164 | }); 165 | break; 166 | case "OPCODE_WRQ": 167 | sendError(peer, ERR_ACCESS_VIOLATION, 'Read only tftp server'); 168 | break; 169 | case "OPCODE_DATA": 170 | sendError(peer, ERR_ACCESS_VIOLATION, 'Read only tftp server'); 171 | break; 172 | case "OPCODE_ACK": 173 | buf = msg.slice(2); 174 | var block = (parseInt(buf[0]) << 8) +parseInt(buf[1]); 175 | continueSession(peer, block + 1); 176 | break; 177 | case "OPCODE_ERROR": 178 | clearSession(peer); 179 | break; 180 | } 181 | }); 182 | 183 | sock.on('listening', function() { 184 | slog('Bound to '+ SERVER_HOST + ':' + SERVER_PORT); 185 | }); 186 | 187 | sock.bind(SERVER_PORT, SERVER_HOST); 188 | --------------------------------------------------------------------------------