pixelflut-udp/client.js

72 lines
2.5 KiB
JavaScript
Raw Permalink Normal View History

2021-11-17 19:26:59 +00:00
const
BUFFER = true,
BUFFER_INTERVAL = 50,
PEER_PUBLIC_KEY = "e3950b1762fff528bc891ae227006ce6ba88eb9573ea0d3fb97785163f7eb330",
PEER_ADDRESS = "pixelflut.semisol.net",
PORT = 1338,
SECURE = true,
LISTEN_PORT = 1337,
SIZE = [1024, 768]
!async function () {
let dgram = require("dgram")
let crypto = require("crypto")
let net = require("net")
let readline = require("readline")
let monocypher = require("monocypher-wasm")
let udpClient = dgram.createSocket({ type: "udp4" })
await monocypher.ready
let pubkey, shared
if (SECURE) {
let key = crypto.randomBytes(32)
pubkey = monocypher.crypto_key_exchange_public_key(key)
shared = monocypher.crypto_key_exchange(key, Buffer.from(PEER_PUBLIC_KEY, "hex"))
if (!shared) {
console.error("Failed to perform key exchange")
process.exit(1)
}
}
let queue = []
net.createServer((sock) => {
let rl = readline.createInterface(sock)
rl.on("line", (l) => {
let data = l.split(" ")
if (data.length === 1 && data[0] === "SIZE") {
sock.write("SIZE " + SIZE.join(" ") + "\n")
}
if (data.length === 4 && data[0] === "PX") {
let x = parseInt(data[1], 10)
let y = parseInt(data[2], 10)
let r = parseInt(data[3].slice(0, 2), 16)
let g = parseInt(data[3].slice(2, 4), 16)
let b = parseInt(data[3].slice(4, 6), 16)
if (
check(x, 0xfff) ||
check(y, 0xfff) ||
check(r, 0xff) ||
check(g, 0xff) ||
check(b, 0xff)
) return
queue.push(x >> 4, ((x & 0xf) << 4) | (y >> 8), y & 0xff, r, g, b)
if (!BUFFER || queue.length > 1000) processQueue()
}
})
sock.on("close", () => rl.close())
sock.on("error", () => sock.end())
}).listen(LISTEN_PORT)
udpClient.bind()
if (BUFFER) setInterval(() => {
if (queue.length > 0) processQueue()
}, BUFFER_INTERVAL)
function processQueue() {
let data = Buffer.from(queue)
queue = []
if (SECURE) {
let nonce = crypto.randomBytes(24)
data = Buffer.concat([pubkey, nonce, monocypher.crypto_lock(shared, nonce, data)])
}
udpClient.send(data, PORT, PEER_ADDRESS)
}
function check(num, max) {
return isNaN(num) || num < 0 || num >= max
}
}()