diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..294210d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,507 @@ +{ + "name": "red-briq-nodes", + "version": "0.2.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@xmpp/jid": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@xmpp/jid/-/jid-0.0.2.tgz", + "integrity": "sha1-DVKMqdWNr8gzZlVk/+YvMyoxZ/I=" + }, + "@xmpp/streamparser": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@xmpp/streamparser/-/streamparser-0.0.6.tgz", + "integrity": "sha1-EYAz6p23yGoctGED8mnr/3n28eo=", + "requires": { + "@xmpp/xml": "^0.1.3", + "inherits": "^2.0.3", + "ltx": "^2.5.0" + } + }, + "@xmpp/xml": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@xmpp/xml/-/xml-0.1.3.tgz", + "integrity": "sha1-HxQ5nlPkGWiFWGmPbGLnHjmoam4=", + "requires": { + "inherits": "^2.0.3", + "ltx": "^2.6.2" + } + }, + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "backoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.3.0.tgz", + "integrity": "sha1-7nx+OAk/kuRyhZ22NedlJFT8Ieo=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "browser-request": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz", + "integrity": "sha1-ns5bWsqJopkyJC4Yv5M975h2zBc=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "ltx": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/ltx/-/ltx-2.9.2.tgz", + "integrity": "sha512-llB7HflFhlfsYYT1SAe80elCBO5C20ryLdwPB/A/BZk38hhVeZztDlWQ9uTyvKNPX4aK6sA+JfS1f/mfzp5cxA==", + "requires": { + "inherits": "^2.0.4" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node-xmpp-client": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/node-xmpp-client/-/node-xmpp-client-3.2.0.tgz", + "integrity": "sha1-r0Un3wzFq9JpDLohOcwezcgeoYk=", + "requires": { + "browser-request": "^0.3.3", + "debug": "^2.2.0", + "md5.js": "^1.3.3", + "minimist": "^1.2.0", + "node-xmpp-core": "^5.0.9", + "request": "^2.65.0", + "ws": "^1.1.1" + } + }, + "node-xmpp-core": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/node-xmpp-core/-/node-xmpp-core-5.0.9.tgz", + "integrity": "sha1-XCjCjtsfs/i+uixnYHd2E/SPNCo=", + "requires": { + "@xmpp/jid": "^0.0.2", + "@xmpp/streamparser": "^0.0.6", + "@xmpp/xml": "^0.1.3", + "debug": "^2.2.0", + "inherits": "^2.0.1", + "lodash.assign": "^4.0.0", + "node-xmpp-tls-connect": "^1.0.1", + "reconnect-core": "https://github.com/dodo/reconnect-core/tarball/merged" + } + }, + "node-xmpp-tls-connect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/node-xmpp-tls-connect/-/node-xmpp-tls-connect-1.0.1.tgz", + "integrity": "sha1-kazkOsJrE4hhsr5HjfnfGdYdxcM=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/qbox/-/qbox-0.1.7.tgz", + "integrity": "sha1-6A8NxdCfhp2IghaMP2asjdKEDwI=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "reconnect-core": { + "version": "https://github.com/dodo/reconnect-core/tarball/merged", + "integrity": "sha512-wZK/v5ZaNaSUs2Wnwh2YSX/Jqv6bQHKNEwojdzV11tByKziR9ikOssf5tvUhx+8/oCBz6AakOFAjZuqPoiRHJQ==", + "requires": { + "backoff": "~2.3.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "simple-xmpp": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-xmpp/-/simple-xmpp-1.3.1.tgz", + "integrity": "sha512-o0wGVlI8Q4o0qTz6Kylbo1QPOMVn+DA/vyHHZecqcQ+LK4ZWGe3wtRON9QjHAkSyxB36PoagmiUz4pHADau8Mw==", + "requires": { + "node-xmpp-client": "^3.0.0", + "qbox": "0.1.x" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } +} diff --git a/package.json b/package.json index 3e32aa3..cbca5f3 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,26 @@ { - "name" : "node-red-node-xmpp", - "version" : "0.2.4", - "description" : "A Node-RED node to talk to an XMPP server", - "dependencies" : { - "simple-xmpp" : "^1.3.1" + "name": "red-briq-nodes", + "version": "0.2.4", + "description": "A Node-RED node to talk to an XMPP server", + "dependencies": { + "denque": "^1.4.1", + "simple-xmpp": "^1.3.1" }, - "repository" : { - "type":"git", - "url":"https://github.com/node-red/node-red-nodes/tree/master/social/xmpp" + "repository": { + "type": "git", + "url": "https://github.com/node-red/node-red-nodes/tree/master/social/xmpp" }, "license": "Apache-2.0", - "keywords": [ "node-red", "xmpp" ], - "node-red" : { - "nodes" : { - "xmpp": "92-xmpp.js", - "my-debounce": "my-debounce.js", - "command-parse": "command-parse.js" + "keywords": [ + "node-red", + "xmpp" + ], + "node-red": { + "nodes": { + "xmpp": "red/xmpp/92-xmpp.js", + "my-debounce": "red/my-debounce/my-debounce.js", + "command-parse": "red/command-parse/command-parse.js", + "briq-tcp": "red/tcp/tcp.js" } }, "author": { diff --git a/command-parse.html b/red/command-parse/command-parse.html similarity index 100% rename from command-parse.html rename to red/command-parse/command-parse.html diff --git a/command-parse.js b/red/command-parse/command-parse.js similarity index 100% rename from command-parse.js rename to red/command-parse/command-parse.js diff --git a/my-debounce.html b/red/my-debounce/my-debounce.html similarity index 100% rename from my-debounce.html rename to red/my-debounce/my-debounce.html diff --git a/my-debounce.js b/red/my-debounce/my-debounce.js similarity index 100% rename from my-debounce.js rename to red/my-debounce/my-debounce.js diff --git a/red/tcp/locales/en-US/tcp.json b/red/tcp/locales/en-US/tcp.json new file mode 100644 index 0000000..6737b61 --- /dev/null +++ b/red/tcp/locales/en-US/tcp.json @@ -0,0 +1,57 @@ +{ + "tcpin": { + "label": { + "type": "Type", + "output": "Output", + "port": "port", + "host": "at host", + "payload": "payload(s)", + "delimited": "delimited by", + "close-connection": "Close connection after each message is sent?", + "decode-base64": "Decode Base64 message?", + "server": "Server", + "return": "Return", + "ms": "ms", + "chars": "chars" + }, + "type": { + "listen": "Listen on", + "connect": "Connect to", + "reply": "Reply to TCP" + }, + "output": { + "stream": "stream of", + "single": "single", + "buffer": "Buffer", + "string": "String", + "base64": "Base64 String" + }, + "return": { + "timeout": "after a fixed timeout of", + "character": "when character received is", + "number": "a fixed number of chars", + "never": "never - keep connection open", + "immed": "immediately - don't wait for reply" + }, + "status": { + "connecting": "connecting to __host__:__port__", + "connected": "connected to __host__:__port__", + "listening-port": "listening on port __port__", + "stopped-listening": "stopped listening on port", + "connection-from": "connection from __host__:__port__", + "connection-closed": "connection closed from __host__:__port__", + "connections": "__count__ connection", + "connections_plural": "__count__ connections" + }, + "errors": { + "connection-lost": "connection lost to __host__:__port__", + "timeout": "timeout closed socket port __port__", + "cannot-listen": "unable to listen on port __port__, error: __error__", + "error": "error: __error__", + "socket-error": "socket error from __host__:__port__", + "no-host": "Host and/or port not set", + "connect-timeout": "connect timeout", + "connect-fail": "connect failed" + } + } +} \ No newline at end of file diff --git a/red/tcp/tcp.html b/red/tcp/tcp.html new file mode 100644 index 0000000..af5cfd6 --- /dev/null +++ b/red/tcp/tcp.html @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/red/tcp/tcp.js b/red/tcp/tcp.js new file mode 100644 index 0000000..e92ea48 --- /dev/null +++ b/red/tcp/tcp.js @@ -0,0 +1,715 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var reconnectTime = RED.settings.socketReconnectTime||10000; + var socketTimeout = RED.settings.socketTimeout||null; + const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000; + const Denque = require('denque'); + var net = require('net'); + + var connectionPool = {}; + + /** + * Enqueue `item` in `queue` + * @param {Denque} queue - Queue + * @param {*} item - Item to enqueue + * @private + * @returns {Denque} `queue` + */ + const enqueue = (queue, item) => { + // drop msgs from front of queue if size is going to be exceeded + if (queue.length === msgQueueSize) { queue.shift(); } + queue.push(item); + return queue; + }; + + /** + * Shifts item off front of queue + * @param {Deque} queue - Queue + * @private + * @returns {*} Item previously at front of queue + */ + const dequeue = queue => queue.shift(); + + function TcpIn(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port * 1; + this.topic = n.topic; + this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/ + this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */ + this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r"); + this.base64 = n.base64; + this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server"); + this.closing = false; + this.connected = false; + var node = this; + var count = 0; + + if (!node.server) { + var buffer = null; + var client; + var reconnectTimeout; + var end = false; + var setupTcpClient = function() { + node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port})); + node.status({fill:"grey",shape:"dot",text:"common.status.connecting"}); + var id = (1+Math.random()*4294967295).toString(16); + client = net.connect(node.port, node.host, function() { + buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : ""; + node.connected = true; + node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port})); + node.status({fill:"green",shape:"dot",text:"common.status.connected"}); + }); + client.setKeepAlive(true,120000); + connectionPool[id] = client; + + client.on('data', function (data) { + if (node.datatype != 'buffer') { + data = data.toString(node.datatype); + } + if (node.stream) { + var msg; + if ((node.datatype) === "utf8" && node.newline !== "") { + buffer = buffer+data; + var parts = buffer.split(node.newline); + for (var i = 0; i 0)) { + var msg = {topic:node.topic, payload:buffer}; + msg._session = {type:"tcp",id:id}; + if (buffer.length !== 0) { + end = true; // only ask for fast re-connect if we actually got something + node.send(msg); + } + buffer = null; + } + }); + client.on('close', function() { + delete connectionPool[id]; + node.connected = false; + node.status({fill:"red",shape:"ring",text:"common.status.disconnected"}); + if (!node.closing) { + if (end) { // if we were asked to close then try to reconnect once very quick. + end = false; + reconnectTimeout = setTimeout(setupTcpClient, 20); + } + else { + node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port})); + reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); + } + } else { + if (node.doneClose) { node.doneClose(); } + } + }); + client.on('error', function(err) { + node.log(err); + }); + } + setupTcpClient(); + + this.on('close', function(done) { + node.doneClose = done; + this.closing = true; + if (client) { client.destroy(); } + clearTimeout(reconnectTimeout); + if (!node.connected) { done(); } + }); + } + else { + var server = net.createServer(function (socket) { + socket.setKeepAlive(true,120000); + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + var id = (1+Math.random()*4294967295).toString(16); + var fromi; + var fromp; + connectionPool[id] = socket; + count++; + node.status({ + text:RED._("tcpin.status.connections",{count:count}), + event:"connect", + ip:socket.remoteAddress, + port:socket.remotePort, + _session: {type:"tcp",id:id} + }); + + var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : ""; + socket.on('data', function (data) { + if (node.datatype != 'buffer') { + data = data.toString(node.datatype); + } + if (node.stream) { + var msg; + if ((typeof data) === "string" && node.newline !== "") { + buffer = buffer+data; + var parts = buffer.split(node.newline); + for (var i = 0; i 0) { + var msg = {topic:node.topic, payload:buffer, ip:fromi, port:fromp}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + buffer = null; + } + }); + socket.on('timeout', function() { + node.log(RED._("tcpin.errors.timeout",{port:node.port})); + socket.end(); + }); + socket.on('close', function() { + delete connectionPool[id]; + count--; + node.status({ + text:RED._("tcpin.status.connections",{count:count}), + event:"disconnect", + ip:socket.remoteAddress, + port:socket.remotePort, + _session: {type:"tcp",id:id} + + }); + }); + socket.on('error',function(err) { + node.log(err); + }); + }); + + server.on('error', function(err) { + if (err) { + node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()})); + } + }); + + server.listen(node.port, function(err) { + if (err) { + node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()})); + } else { + node.log(RED._("tcpin.status.listening-port",{port:node.port})); + node.on('close', function() { + for (var c in connectionPool) { + if (connectionPool.hasOwnProperty(c)) { + connectionPool[c].end(); + connectionPool[c].unref(); + } + } + node.closing = true; + server.close(); + node.log(RED._("tcpin.status.stopped-listening",{port:node.port})); + }); + } + }); + } + } + RED.nodes.registerType("briq tcp in",TcpIn); + + + function TcpOut(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port * 1; + this.base64 = n.base64; + this.doend = n.end || false; + this.beserver = n.beserver; + this.name = n.name; + this.closing = false; + this.connected = false; + var node = this; + + if (!node.beserver||node.beserver=="client") { + var reconnectTimeout; + var client = null; + var end = false; + + var setupTcpClient = function() { + node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port})); + node.status({fill:"grey",shape:"dot",text:"common.status.connecting"}); + client = net.connect(node.port, node.host, function() { + node.connected = true; + node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port})); + node.status({fill:"green",shape:"dot",text:"common.status.connected"}); + }); + client.setKeepAlive(true,120000); + client.on('error', function (err) { + node.log(RED._("tcpin.errors.error",{error:err.toString()})); + }); + client.on('end', function (err) { + node.status({}); + node.connected = false; + }); + client.on('close', function() { + node.status({fill:"red",shape:"ring",text:"common.status.disconnected"}); + node.connected = false; + client.destroy(); + if (!node.closing) { + if (end) { + end = false; + reconnectTimeout = setTimeout(setupTcpClient,20); + } + else { + node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port})); + reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); + } + } else { + if (node.doneClose) { node.doneClose(); } + } + }); + } + setupTcpClient(); + + node.on("input", function(msg,nodeSend,nodeDone) { + if (node.connected && msg.payload != null) { + if (Buffer.isBuffer(msg.payload)) { + client.write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + client.write(Buffer.from(msg.payload,'base64')); + } else { + client.write(Buffer.from(""+msg.payload)); + } + if (node.doend === true) { + end = true; + if (client) { node.status({}); client.destroy(); } + } + } + nodeDone(); + }); + + node.on("close", function(done) { + node.doneClose = done; + this.closing = true; + if (client) { client.destroy(); } + clearTimeout(reconnectTimeout); + if (!node.connected) { done(); } + }); + + } + else if (node.beserver == "reply") { + node.on("input",function(msg, nodeSend, nodeDone) { + if (msg._session && msg._session.type == "tcp") { + var client = connectionPool[msg._session.id]; + if (client) { + if (Buffer.isBuffer(msg.payload)) { + client.write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + client.write(Buffer.from(msg.payload,'base64')); + } else { + client.write(Buffer.from(""+msg.payload)); + } + } + } + else { + for (var i in connectionPool) { + if (Buffer.isBuffer(msg.payload)) { + connectionPool[i].write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + connectionPool[i].write(Buffer.from(msg.payload,'base64')); + } else { + connectionPool[i].write(Buffer.from(""+msg.payload)); + } + } + } + nodeDone(); + }); + } + else { + var connectedSockets = []; + node.status({text:RED._("tcpin.status.connections",{count:0})}); + var server = net.createServer(function (socket) { + socket.setKeepAlive(true,120000); + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + node.log(RED._("tcpin.status.connection-from",{host:socket.remoteAddress, port:socket.remotePort})); + connectedSockets.push(socket); + node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})}); + socket.on('timeout', function() { + node.log(RED._("tcpin.errors.timeout",{port:node.port})); + socket.end(); + }); + socket.on('close',function() { + node.log(RED._("tcpin.status.connection-closed",{host:socket.remoteAddress, port:socket.remotePort})); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})}); + }); + socket.on('error',function() { + node.log(RED._("tcpin.errors.socket-error",{host:socket.remoteAddress, port:socket.remotePort})); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})}); + }); + }); + + node.on("input", function(msg, nodeSend, nodeDone) { + if (msg.payload != null) { + var buffer; + if (Buffer.isBuffer(msg.payload)) { + buffer = msg.payload; + } else if (typeof msg.payload === "string" && node.base64) { + buffer = Buffer.from(msg.payload,'base64'); + } else { + buffer = Buffer.from(""+msg.payload); + } + for (var i = 0; i < connectedSockets.length; i += 1) { + if (node.doend === true) { connectedSockets[i].end(buffer); } + else { connectedSockets[i].write(buffer); } + } + } + nodeDone(); + }); + + server.on('error', function(err) { + if (err) { + node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()})); + } + }); + + server.listen(node.port, function(err) { + if (err) { + node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()})); + } else { + node.log(RED._("tcpin.status.listening-port",{port:node.port})); + node.on('close', function() { + for (var c in connectedSockets) { + if (connectedSockets.hasOwnProperty(c)) { + connectedSockets[c].end(); + connectedSockets[c].unref(); + } + } + server.close(); + node.log(RED._("tcpin.status.stopped-listening",{port:node.port})); + }); + } + }); + } + } + RED.nodes.registerType("briq tcp out",TcpOut); + + + function TcpGet(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.port = Number(n.port); + this.out = n.out; + this.splitc = n.splitc; + + if (this.out === "immed") { this.splitc = -1; this.out = "time"; } + if (this.out !== "char") { this.splitc = Number(this.splitc); } + else { + if (this.splitc[0] == '\\') { + this.splitc = parseInt(this.splitc.replace("\\n",0x0A).replace("\\r",0x0D).replace("\\t",0x09).replace("\\e",0x1B).replace("\\f",0x0C).replace("\\0",0x00)); + } // jshint ignore:line + if (typeof this.splitc == "string") { + if (this.splitc.substr(0,2) == "0x") { + this.splitc = parseInt(this.splitc); + } + else { + this.splitc = this.splitc.charCodeAt(0); + } + } // jshint ignore:line + } + + var node = this; + + var clients = {}; + + this.on("input", function(msg, nodeSend, nodeDone) { + var i = 0; + if ((!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) { + msg.payload = msg.payload.toString(); + } + + var host = node.server || msg.host; + var port = node.port || msg.port; + + // Store client information independently + // the clients object will have: + // clients[id].client, clients[id].msg, clients[id].timeout + var connection_id = host + ":" + port; + if (connection_id !== node.last_id) { + node.status({}); + node.last_id = connection_id; + } + clients[connection_id] = clients[connection_id] || { + msgQueue: new Denque(), + connected: false, + connecting: false + }; + enqueue(clients[connection_id].msgQueue, {msg:msg,nodeSend:nodeSend, nodeDone: nodeDone}); + clients[connection_id].lastMsg = msg; + + if (!clients[connection_id].connecting && !clients[connection_id].connected) { + var buf; + if (this.out == "count") { + if (this.splitc === 0) { buf = Buffer.alloc(1); } + else { buf = Buffer.alloc(this.splitc); } + } + else { buf = Buffer.alloc(65536); } // set it to 64k... hopefully big enough for most TCP packets.... but only hopefully + + clients[connection_id].client = net.Socket(); + if (socketTimeout !== null) { clients[connection_id].client.setTimeout(socketTimeout);} + + if (host && port) { + clients[connection_id].connecting = true; + clients[connection_id].client.connect(port, host, function() { + //node.log(RED._("tcpin.errors.client-connected")); + node.status({fill:"green",shape:"dot",text:"common.status.connected"}); + if (clients[connection_id] && clients[connection_id].client) { + clients[connection_id].connected = true; + clients[connection_id].connecting = false; + let event; + while (event = dequeue(clients[connection_id].msgQueue)) { + clients[connection_id].client.write(event.msg.payload); + event.nodeDone(); + } + if (node.out === "time" && node.splitc < 0) { + clients[connection_id].connected = clients[connection_id].connecting = false; + clients[connection_id].client.end(); + delete clients[connection_id]; + node.status({}); + } + } + }); + } + else { + node.warn(RED._("tcpin.errors.no-host")); + } + + clients[connection_id].client.on('data', function(data) { + if (node.out === "sit") { // if we are staying connected just send the buffer + if (clients[connection_id]) { + const msg = clients[connection_id].lastMsg || {}; + msg.payload = data; + nodeSend(RED.util.cloneMessage(msg)); + } + } + // else if (node.splitc === 0) { + // clients[connection_id].msg.payload = data; + // node.send(clients[connection_id].msg); + // } + else { + for (var j = 0; j < data.length; j++ ) { + if (node.out === "time") { + if (clients[connection_id]) { + // do the timer thing + if (clients[connection_id].timeout) { + i += 1; + buf[i] = data[j]; + } + else { + clients[connection_id].timeout = setTimeout(function () { + if (clients[connection_id]) { + clients[connection_id].timeout = null; + const msg = clients[connection_id].lastMsg || {}; + msg.payload = Buffer.alloc(i+1); + buf.copy(msg.payload,0,0,i+1); + nodeSend(msg); + if (clients[connection_id].client) { + node.status({}); + clients[connection_id].client.destroy(); + delete clients[connection_id]; + } + } + }, node.splitc); + i = 0; + buf[0] = data[j]; + } + } + } + // count bytes into a buffer... + else if (node.out == "count") { + buf[i] = data[j]; + i += 1; + if ( i >= node.splitc) { + if (clients[connection_id]) { + const msg = clients[connection_id].lastMsg || {}; + msg.payload = Buffer.alloc(i); + buf.copy(msg.payload,0,0,i); + nodeSend(msg); + if (clients[connection_id].client) { + node.status({}); + clients[connection_id].client.destroy(); + delete clients[connection_id]; + } + i = 0; + } + } + } + // look for a char + else { + buf[i] = data[j]; + i += 1; + if (data[j] == node.splitc) { + if (clients[connection_id]) { + const msg = clients[connection_id].lastMsg || {}; + msg.payload = Buffer.alloc(i); + buf.copy(msg.payload,0,0,i); + nodeSend(msg); + if (clients[connection_id].client) { + node.status({}); + clients[connection_id].client.destroy(); + delete clients[connection_id]; + } + i = 0; + } + } + } + } + } + }); + + clients[connection_id].client.on('end', function() { + //console.log("END"); + node.status({fill:"grey",shape:"ring",text:"common.status.disconnected"}); + if (clients[connection_id] && clients[connection_id].client) { + clients[connection_id].connected = clients[connection_id].connecting = false; + clients[connection_id].client = null; + } + }); + + clients[connection_id].client.on('close', function() { + //console.log("CLOSE"); + if (clients[connection_id]) { + clients[connection_id].connected = clients[connection_id].connecting = false; + } + + var anyConnected = false; + + for (var client in clients) { + if (clients[client].connected) { + anyConnected = true; + break; + } + } + if (node.doneClose && !anyConnected) { + clients = {}; + node.doneClose(); + } + }); + + clients[connection_id].client.on('error', function() { + //console.log("ERROR"); + node.status({fill:"red",shape:"ring",text:"common.status.error"}); + node.error(RED._("tcpin.errors.connect-fail") + " " + connection_id, msg); + if (clients[connection_id] && clients[connection_id].client) { + clients[connection_id].client.destroy(); + delete clients[connection_id]; + } + }); + + clients[connection_id].client.on('timeout',function() { + //console.log("TIMEOUT"); + if (clients[connection_id]) { + clients[connection_id].connected = clients[connection_id].connecting = false; + node.status({fill:"grey",shape:"dot",text:"tcpin.errors.connect-timeout"}); + //node.warn(RED._("tcpin.errors.connect-timeout")); + if (clients[connection_id].client) { + clients[connection_id].connecting = true; + clients[connection_id].client.connect(port, host, function() { + clients[connection_id].connected = true; + clients[connection_id].connecting = false; + node.status({fill:"green",shape:"dot",text:"common.status.connected"}); + }); + } + } + }); + } + else if (!clients[connection_id].connecting && clients[connection_id].connected) { + if (clients[connection_id] && clients[connection_id].client) { + let event = dequeue(clients[connection_id].msgQueue) + clients[connection_id].client.write(event.msg.payload); + event.nodeDone(); + } + } + }); + + this.on("close", function(done) { + node.doneClose = done; + for (var cl in clients) { + if (clients[cl].hasOwnProperty("client")) { + clients[cl].client.destroy(); + } + } + node.status({}); + + // this is probably not necessary and may be removed + var anyConnected = false; + for (var c in clients) { + if (clients[c].connected) { + anyConnected = true; + break; + } + } + if (!anyConnected) { clients = {}; } + done(); + }); + + } + RED.nodes.registerType("briq tcp request",TcpGet); + function TcpClose(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + var node = this; + + node.on("input",function(msg, nodeSend, nodeDone) { + if (msg._session && msg._session.type == "tcp") { + var client = connectionPool[msg._session.id]; + if (client) { + client.destroy(); + } + } + nodeDone(); + }); + } + RED.nodes.registerType("briq tcp close", TcpClose); +} \ No newline at end of file diff --git a/92-xmpp.html b/red/xmpp/92-xmpp.html similarity index 100% rename from 92-xmpp.html rename to red/xmpp/92-xmpp.html diff --git a/92-xmpp.js b/red/xmpp/92-xmpp.js similarity index 100% rename from 92-xmpp.js rename to red/xmpp/92-xmpp.js