sodium
This commit is contained in:
parent
4372e66d57
commit
75c68e0134
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
|
@ -0,0 +1,301 @@
|
||||||
|
{
|
||||||
|
"name": "system",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"libsodium": "^0.7.13",
|
||||||
|
"sodium-native": "^4.0.6",
|
||||||
|
"sodium-plus": "^0.9.0",
|
||||||
|
"webrtc-adapter": "^8.2.3",
|
||||||
|
"websocket": "^1.0.34"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/big-integer": {
|
||||||
|
"version": "1.6.52",
|
||||||
|
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
|
||||||
|
"integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bufferutil": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
|
||||||
|
"dependencies": {
|
||||||
|
"es5-ext": "^0.10.50",
|
||||||
|
"type": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es5-ext": {
|
||||||
|
"version": "0.10.62",
|
||||||
|
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
|
||||||
|
"integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"es6-iterator": "^2.0.3",
|
||||||
|
"es6-symbol": "^3.1.3",
|
||||||
|
"next-tick": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es6-iterator": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "1",
|
||||||
|
"es5-ext": "^0.10.35",
|
||||||
|
"es6-symbol": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es6-symbol": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "^1.0.1",
|
||||||
|
"ext": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ext": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||||
|
"dependencies": {
|
||||||
|
"type": "^2.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ext/node_modules/type": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
|
||||||
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/is-typedarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
|
||||||
|
},
|
||||||
|
"node_modules/libsodium": {
|
||||||
|
"version": "0.7.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz",
|
||||||
|
"integrity": "sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw=="
|
||||||
|
},
|
||||||
|
"node_modules/libsodium-wrappers": {
|
||||||
|
"version": "0.7.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.13.tgz",
|
||||||
|
"integrity": "sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==",
|
||||||
|
"dependencies": {
|
||||||
|
"libsodium": "^0.7.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
},
|
||||||
|
"node_modules/next-tick": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
|
||||||
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
|
||||||
|
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/poly1305-js": {
|
||||||
|
"version": "0.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/poly1305-js/-/poly1305-js-0.4.4.tgz",
|
||||||
|
"integrity": "sha512-5B6/S+vg5AOr66wJDkh5LOpU/F3EKANDy4VXKsNZLXea1uCy6CiOWOZ3VhcC0nYdhE7vJUMcLxqcVlrv2g/+Rg==",
|
||||||
|
"dependencies": {
|
||||||
|
"big-integer": "^1.6.51"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sdp": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw=="
|
||||||
|
},
|
||||||
|
"node_modules/sodium-native": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-uYsyycwcz9kYDwpXxJmL2YZosynsxcP6RPySbARVJdC9uNDa2CMjzJ7/WsMMvThKgvAYsBWdZc7L/WSVj9lTcA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sodium-plus": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sodium-plus/-/sodium-plus-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-WWKxrd81qDL7C1A10yxNmZ135yovEZuIRnZ/BIf/FcajYBupbKbPdgzwlusPHLVxkMDDamcarq9PxxRBUSqpCw==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.6.0",
|
||||||
|
"libsodium-wrappers": "^0.7.6",
|
||||||
|
"poly1305-js": "^0.4.2",
|
||||||
|
"typedarray-to-buffer": "^3.1.5",
|
||||||
|
"xsalsa20": "^1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"sodium-native": "^3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/type": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
|
||||||
|
},
|
||||||
|
"node_modules/typedarray-to-buffer": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-typedarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/utf-8-validate": {
|
||||||
|
"version": "5.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||||
|
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webrtc-adapter": {
|
||||||
|
"version": "8.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-8.2.3.tgz",
|
||||||
|
"integrity": "sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"sdp": "^3.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0",
|
||||||
|
"npm": ">=3.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/websocket": {
|
||||||
|
"version": "1.0.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
|
||||||
|
"integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"debug": "^2.2.0",
|
||||||
|
"es5-ext": "^0.10.50",
|
||||||
|
"typedarray-to-buffer": "^3.1.5",
|
||||||
|
"utf-8-validate": "^5.0.2",
|
||||||
|
"yaeti": "^0.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xsalsa20": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xsalsa20/-/xsalsa20-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w=="
|
||||||
|
},
|
||||||
|
"node_modules/yaeti": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"libsodium": "^0.7.13",
|
||||||
|
"sodium-native": "^4.0.6",
|
||||||
|
"sodium-plus": "^0.9.0",
|
||||||
|
"webrtc-adapter": "^8.2.3",
|
||||||
|
"websocket": "^1.0.34"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { SodiumPlus, X25519SecretKey } = require("sodium-plus");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const sodium = await SodiumPlus.auto();
|
||||||
|
|
||||||
|
fs.readFile("../settings/secret.txt", "utf8", async (err, data) => {
|
||||||
|
let key;
|
||||||
|
|
||||||
|
if (err || data.length === 0) {
|
||||||
|
const keys = await sodium.crypto_box_keypair();
|
||||||
|
|
||||||
|
const secret = await sodium.crypto_box_secretkey(keys);
|
||||||
|
key = await sodium.sodium_bin2hex(
|
||||||
|
(await sodium.crypto_box_publickey(keys)).getBuffer(),
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.writeFile(
|
||||||
|
"../settings/secret.txt",
|
||||||
|
await sodium.sodium_bin2hex(secret.getBuffer()),
|
||||||
|
() => {},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
key = await sodium.sodium_bin2hex(
|
||||||
|
(await sodium.crypto_box_publickey_from_secretkey(
|
||||||
|
await X25519SecretKey.from(data, "hex"),
|
||||||
|
)).getBuffer(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(
|
||||||
|
`https://notchat.mirzaev.sexy/servers/connect/MIRZAEV`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
description: "",
|
||||||
|
location: "Russia",
|
||||||
|
host: "https://pantry.bebra.team",
|
||||||
|
accounts: [],
|
||||||
|
settings: {
|
||||||
|
chats: {
|
||||||
|
max: 50,
|
||||||
|
private: false,
|
||||||
|
languages: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.then((response) =>
|
||||||
|
Number(response.headers.get("content-length")) === 0
|
||||||
|
? null
|
||||||
|
: response.json()
|
||||||
|
)
|
||||||
|
.then((data) => {
|
||||||
|
if (
|
||||||
|
data !== null &&
|
||||||
|
typeof data !== "undefined" &&
|
||||||
|
data.errors !== null &&
|
||||||
|
typeof data.errors === "object" &&
|
||||||
|
data.errors.length > 0
|
||||||
|
) {
|
||||||
|
console.log("Response from server:\n");
|
||||||
|
for (const error of data.errors) console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
|
@ -0,0 +1,357 @@
|
||||||
|
//#!/usr/bin/env node
|
||||||
|
//
|
||||||
|
// WebSocket chat server
|
||||||
|
// Implemented using Node.js
|
||||||
|
//
|
||||||
|
// Requires the websocket module.
|
||||||
|
//
|
||||||
|
// WebSocket and WebRTC based multi-user chat sample with two-way video
|
||||||
|
// calling, including use of TURN if applicable or necessary.
|
||||||
|
//
|
||||||
|
// This file contains the JavaScript code that implements the server-side
|
||||||
|
// functionality of the chat system, including user ID management, message
|
||||||
|
// reflection, and routing of private messages, including support for
|
||||||
|
// sending through unknown JSON objects to support custom apps and signaling
|
||||||
|
// for WebRTC.
|
||||||
|
//
|
||||||
|
// Requires Node.js and the websocket module (WebSocket-Node):
|
||||||
|
//
|
||||||
|
// - http://nodejs.org/
|
||||||
|
// - https://github.com/theturtle32/WebSocket-Node
|
||||||
|
//
|
||||||
|
// To read about how this sample works: http://bit.ly/webrtc-from-chat
|
||||||
|
//
|
||||||
|
// Any copyright is dedicated to the Public Domain.
|
||||||
|
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var http = require('http');
|
||||||
|
var https = require('https');
|
||||||
|
var fs = require('fs');
|
||||||
|
var WebSocketServer = require('websocket').server;
|
||||||
|
|
||||||
|
// Pathnames of the SSL key and certificate files to use for
|
||||||
|
// HTTPS connections.
|
||||||
|
|
||||||
|
const keyFilePath = "/etc/letsencrypt/live/bebra.team/privkey.pem";
|
||||||
|
// const certFilePath = "/etc/letsencrypt/live/bebra.ateam/cert.pem";
|
||||||
|
const certFilePath = "/etc/letsencrypt/live/bebra.team/fullchain.pem";
|
||||||
|
|
||||||
|
// Used for managing the text chat user list.
|
||||||
|
|
||||||
|
var connectionArray = [];
|
||||||
|
var nextID = Date.now();
|
||||||
|
var appendToMakeUnique = 1;
|
||||||
|
|
||||||
|
// Output logging information to console
|
||||||
|
|
||||||
|
function log(text) {
|
||||||
|
var time = new Date();
|
||||||
|
|
||||||
|
console.log("[" + time.toLocaleTimeString() + "] " + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you want to implement support for blocking specific origins, this is
|
||||||
|
// where you do it. Just return false to refuse WebSocket connections given
|
||||||
|
// the specified origin.
|
||||||
|
function originIsAllowed(origin) {
|
||||||
|
return true; // We will accept all connections
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scans the list of users and see if the specified name is unique. If it is,
|
||||||
|
// return true. Otherwise, returns false. We want all users to have unique
|
||||||
|
// names.
|
||||||
|
function isUsernameUnique(name) {
|
||||||
|
var isUnique = true;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
if (connectionArray[i].username === name) {
|
||||||
|
isUnique = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isUnique;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends a message (which is already stringified JSON) to a single
|
||||||
|
// user, given their username. We use this for the WebRTC signaling,
|
||||||
|
// and we could use it for private text messaging.
|
||||||
|
function sendToOneUser(target, msgString) {
|
||||||
|
var isUnique = true;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
if (connectionArray[i].username === target) {
|
||||||
|
connectionArray[i].sendUTF(msgString);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the list of connections and return the one for the specified
|
||||||
|
// clientID. Each login gets an ID that doesn't change during the session,
|
||||||
|
// so it can be tracked across username changes.
|
||||||
|
function getConnectionForID(id) {
|
||||||
|
var connect = null;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
if (connectionArray[i].clientID === id) {
|
||||||
|
connect = connectionArray[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builds a message object of type "userlist" which contains the names of
|
||||||
|
// all connected users. Used to ramp up newly logged-in users and,
|
||||||
|
// inefficiently, to handle name change notifications.
|
||||||
|
function makeUserListMessage() {
|
||||||
|
var userListMsg = {
|
||||||
|
type: "userlist",
|
||||||
|
users: []
|
||||||
|
};
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// Add the users to the list
|
||||||
|
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
userListMsg.users.push(connectionArray[i].username);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userListMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends a "userlist" message to all chat members. This is a cheesy way
|
||||||
|
// to ensure that every join/drop is reflected everywhere. It would be more
|
||||||
|
// efficient to send simple join/drop messages to each user, but this is
|
||||||
|
// good enough for this simple example.
|
||||||
|
function sendUserListToAll() {
|
||||||
|
var userListMsg = makeUserListMessage();
|
||||||
|
var userListMsgStr = JSON.stringify(userListMsg);
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
connectionArray[i].sendUTF(userListMsgStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Try to load the key and certificate files for SSL so we can
|
||||||
|
// do HTTPS (required for non-local WebRTC).
|
||||||
|
|
||||||
|
var httpsOptions = {
|
||||||
|
key: null,
|
||||||
|
cert: null
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
httpsOptions.key = fs.readFileSync(keyFilePath);
|
||||||
|
try {
|
||||||
|
httpsOptions.cert = fs.readFileSync(certFilePath);
|
||||||
|
} catch(err) {
|
||||||
|
httpsOptions.key = null;
|
||||||
|
httpsOptions.cert = null;
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
httpsOptions.key = null;
|
||||||
|
httpsOptions.cert = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were able to get the key and certificate files, try to
|
||||||
|
// start up an HTTPS server.
|
||||||
|
|
||||||
|
var webServer = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (httpsOptions.key && httpsOptions.cert) {
|
||||||
|
webServer = https.createServer(httpsOptions, handleWebRequest);
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
webServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!webServer) {
|
||||||
|
try {
|
||||||
|
webServer = http.createServer({}, handleWebRequest);
|
||||||
|
} catch(err) {
|
||||||
|
webServer = null;
|
||||||
|
log(`Error attempting to create HTTP(s) server: ${err.toString()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Our HTTPS server does nothing but service WebSocket
|
||||||
|
// connections, so every request just returns 404. Real Web
|
||||||
|
// requests are handled by the main server on the box. If you
|
||||||
|
// want to, you can return real HTML here and serve Web content.
|
||||||
|
|
||||||
|
function handleWebRequest(request, response) {
|
||||||
|
log ("Received request for " + request.url);
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spin up the HTTPS server on the port assigned to this sample.
|
||||||
|
// This will be turned into a WebSocket port very shortly.
|
||||||
|
|
||||||
|
webServer.listen(6503, function() {
|
||||||
|
log("Server is listening on port 6503");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the WebSocket server by converting the HTTPS server into one.
|
||||||
|
|
||||||
|
var wsServer = new WebSocketServer({
|
||||||
|
httpServer: webServer,
|
||||||
|
autoAcceptConnections: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!wsServer) {
|
||||||
|
log("ERROR: Unable to create WbeSocket server!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a "connect" message handler on our WebSocket server. This is
|
||||||
|
// called whenever a user connects to the server's port using the
|
||||||
|
// WebSocket protocol.
|
||||||
|
|
||||||
|
wsServer.on('request', function(request) {
|
||||||
|
if (!originIsAllowed(request.origin)) {
|
||||||
|
request.reject();
|
||||||
|
log("Connection from " + request.origin + " rejected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept the request and get a connection.
|
||||||
|
|
||||||
|
var connection = request.accept("json", request.origin);
|
||||||
|
|
||||||
|
// Add the new connection to our list of connections.
|
||||||
|
|
||||||
|
log("Connection accepted from " + connection.remoteAddress + ".");
|
||||||
|
connectionArray.push(connection);
|
||||||
|
|
||||||
|
connection.clientID = nextID;
|
||||||
|
nextID++;
|
||||||
|
|
||||||
|
// Send the new client its token; it send back a "username" message to
|
||||||
|
// tell us what username they want to use.
|
||||||
|
|
||||||
|
var msg = {
|
||||||
|
type: "id",
|
||||||
|
id: connection.clientID
|
||||||
|
};
|
||||||
|
connection.sendUTF(JSON.stringify(msg));
|
||||||
|
|
||||||
|
// Set up a handler for the "message" event received over WebSocket. This
|
||||||
|
// is a message sent by a client, and may be text to share with other
|
||||||
|
// users, a private message (text or signaling) for one user, or a command
|
||||||
|
// to the server.
|
||||||
|
|
||||||
|
connection.on('message', function(message) {
|
||||||
|
if (message.type === 'utf8') {
|
||||||
|
log("Received Message: " + message.utf8Data);
|
||||||
|
|
||||||
|
// Process incoming data.
|
||||||
|
|
||||||
|
var sendToClients = true;
|
||||||
|
msg = JSON.parse(message.utf8Data);
|
||||||
|
var connect = getConnectionForID(msg.id);
|
||||||
|
|
||||||
|
// Take a look at the incoming object and act on it based
|
||||||
|
// on its type. Unknown message types are passed through,
|
||||||
|
// since they may be used to implement client-side features.
|
||||||
|
// Messages with a "target" property are sent only to a user
|
||||||
|
// by that name.
|
||||||
|
|
||||||
|
switch(msg.type) {
|
||||||
|
// Public, textual message
|
||||||
|
case "message":
|
||||||
|
msg.name = connect.username;
|
||||||
|
msg.text = msg.text.replace(/(<([^>]+)>)/ig, "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Username change
|
||||||
|
case "username":
|
||||||
|
var nameChanged = false;
|
||||||
|
var origName = msg.name;
|
||||||
|
|
||||||
|
// Ensure the name is unique by appending a number to it
|
||||||
|
// if it's not; keep trying that until it works.
|
||||||
|
while (!isUsernameUnique(msg.name)) {
|
||||||
|
msg.name = origName + appendToMakeUnique;
|
||||||
|
appendToMakeUnique++;
|
||||||
|
nameChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the name had to be changed, we send a "rejectusername"
|
||||||
|
// message back to the user so they know their name has been
|
||||||
|
// altered by the server.
|
||||||
|
if (nameChanged) {
|
||||||
|
var changeMsg = {
|
||||||
|
id: msg.id,
|
||||||
|
type: "rejectusername",
|
||||||
|
name: msg.name
|
||||||
|
};
|
||||||
|
connect.sendUTF(JSON.stringify(changeMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this connection's final username and send out the
|
||||||
|
// updated user list to all users. Yeah, we're sending a full
|
||||||
|
// list instead of just updating. It's horribly inefficient
|
||||||
|
// but this is a demo. Don't do this in a real app.
|
||||||
|
connect.username = msg.name;
|
||||||
|
sendUserListToAll();
|
||||||
|
sendToClients = false; // We already sent the proper responses
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the revised message back to JSON and send it out
|
||||||
|
// to the specified client or all clients, as appropriate. We
|
||||||
|
// pass through any messages not specifically handled
|
||||||
|
// in the select block above. This allows the clients to
|
||||||
|
// exchange signaling and other control objects unimpeded.
|
||||||
|
|
||||||
|
if (sendToClients) {
|
||||||
|
var msgString = JSON.stringify(msg);
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// If the message specifies a target username, only send the
|
||||||
|
// message to them. Otherwise, send it to every user.
|
||||||
|
if (msg.target && msg.target !== undefined && msg.target.length !== 0) {
|
||||||
|
sendToOneUser(msg.target, msgString);
|
||||||
|
} else {
|
||||||
|
for (i=0; i<connectionArray.length; i++) {
|
||||||
|
connectionArray[i].sendUTF(msgString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle the WebSocket "close" event; this means a user has logged off
|
||||||
|
// or has been disconnected.
|
||||||
|
connection.on('close', function(reason, description) {
|
||||||
|
// First, remove the connection from the list of connections.
|
||||||
|
connectionArray = connectionArray.filter(function(el, idx, ar) {
|
||||||
|
return el.connected;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now send the updated user list. Again, please don't do this in a
|
||||||
|
// real application. Your users won't like you very much.
|
||||||
|
sendUserListToAll();
|
||||||
|
|
||||||
|
// Build and output log output for close information.
|
||||||
|
|
||||||
|
var logMessage = "Connection closed: " + connection.remoteAddress + " (" +
|
||||||
|
reason;
|
||||||
|
if (description !== null && description.length !== 0) {
|
||||||
|
logMessage += ": " + description;
|
||||||
|
}
|
||||||
|
logMessage += ")";
|
||||||
|
log(logMessage);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
bdbb2fa5198d6badac2cba73aec104c16f46f5dbf9d0225f0656934846a97d29
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
npm install websocket
|
||||||
|
|
||||||
|
npm install webrtc-adapter
|
||||||
|
cp node_modules/webrtc-adapter/out/adapter.js public/
|
||||||
|
|
||||||
|
node public/server.js
|
Loading…
Reference in New Issue