Skip to content
Snippets Groups Projects
Commit 45245553 authored by Tiger Wang's avatar Tiger Wang Committed by Tiger Wang
Browse files

Action on incoming XCDP messages

parent ea422199
No related branches found
No related tags found
1 merge request!69Spycraft: Send and receive XCDP through XMPP
import { client, xml } from "@xmpp/client" import { client, xml } from "@xmpp/client"
import uuid from "uuid" import uuid from "uuid"
// Assumes that both master and slave connection do not have peer ID conflicts, export default class XMPPConnection extends EventTarget {
// and that they do not care when they receive a peer ID that does not exist.
export default class XMPPConnection {
async joinChannel(channel) { async joinChannel(channel) {
const channelIdent = `${channel}@conference.xmpp.lets-draw.live/${this.username}` const channelIdent = `${channel}@conference.xmpp.lets-draw.live/${this.username}`
const presence = xml( const presence = xml(
...@@ -34,6 +32,8 @@ export default class XMPPConnection { ...@@ -34,6 +32,8 @@ export default class XMPPConnection {
} }
constructor() { constructor() {
super()
this.username = uuid.v4().toString() this.username = uuid.v4().toString()
this.online = false this.online = false
this.queue = [] this.queue = []
...@@ -51,19 +51,20 @@ export default class XMPPConnection { ...@@ -51,19 +51,20 @@ export default class XMPPConnection {
xmpp.on("offline", () => { xmpp.on("offline", () => {
this.online = false this.online = false
console.log("", "offline")
}) })
xmpp.on("stanza", async (stanza) => { xmpp.on("stanza", async (stanza) => {
if (stanza.is("message")) { if (stanza.is("message")) {
// await xmpp.send(xml("presence", { type: "unavailable" })) this.dispatchEvent(
// console.log(stanza) new CustomEvent("stanza", {
// await xmpp.stop() detail: stanza,
}),
)
} }
}) })
xmpp.on("online", async (address) => { xmpp.on("online", async (address) => {
console.log("", "online as", address.toString()) /*eslint no-unused-vars: ["error", { "args": "none" }]*/
// Makes itself available // Makes itself available
await xmpp.send(xml("presence")) await xmpp.send(xml("presence"))
...@@ -81,7 +82,8 @@ export default class XMPPConnection { ...@@ -81,7 +82,8 @@ export default class XMPPConnection {
} }
sneakilySendTheOtherTeamOur(secrets) { sneakilySendTheOtherTeamOur(secrets) {
this.joinChannel("imperial") this.joinChannel("imperial").then(
.then(this.sendChannelMessage("imperial", secrets)) this.sendChannelMessage("imperial", secrets),
)
} }
} }
import { computeErasureIntervals, combineErasureIntervals } from "./erasure.js" import {
/* computeErasureIntervals, */ combineErasureIntervals,
} from "./erasure.js"
import XMPP from "./connection/XMPP2.js" import XMPP from "./connection/XMPP2.js"
import { connect } from "./room.js" import { connect } from "./room.js"
...@@ -6,10 +8,11 @@ const DEFAULT_ROOM = "imperial" ...@@ -6,10 +8,11 @@ const DEFAULT_ROOM = "imperial"
let room = null let room = null
let secureLine = null let secureLine = null
let divulgedUpTo = new Map(); const divulgedUpTo = new Map()
const pointPresenceMap = new Map() const pointPresenceMap = new Map()
const pathIDsByXCDPIdentifier = new Map()
function eraseEverythingAtPosition(x, y, radius, room) { /* function eraseEverythingAtPosition(x, y, radius, room) {
const mousePos = [x, y] const mousePos = [x, y]
room.getPaths().forEach((points, pathID) => { room.getPaths().forEach((points, pathID) => {
const prevPathIntervals = const prevPathIntervals =
...@@ -34,74 +37,115 @@ function eraseEverythingAtPosition(x, y, radius, room) { ...@@ -34,74 +37,115 @@ function eraseEverythingAtPosition(x, y, radius, room) {
), ),
) )
}) })
} } */
const onRoomConnect = (room_) => { const onRoomConnect = (room_) => {
room = room_ room = room_
secureLine = new XMPP(); secureLine = new XMPP()
room.addEventListener("addOrUpdatePath", ({ detail: { id, points } }) => { room.addEventListener("addOrUpdatePath", ({ detail: { id, points } }) => {
if (points.length === 0) { if (points.length === 0) {
return; return
} }
let upTo = divulgedUpTo.get(id); let upTo = divulgedUpTo.get(id)
if (upTo === undefined) { if (upTo === undefined) {
upTo = 0; pathIDsByXCDPIdentifier.set(id, id)
upTo = 0
} }
if (upTo === 0) { if (upTo === 0) {
const point = points[0]; const point = points[0]
const colour = point[3]; const colour = point[3]
const R = parseInt(colour.substring(1, 3), 16); const R = parseInt(colour.substring(1, 3), 16)
const G = parseInt(colour.substring(3, 5), 16); const G = parseInt(colour.substring(3, 5), 16)
const B = parseInt(colour.substring(5, 7), 16); const B = parseInt(colour.substring(5, 7), 16)
secureLine.sneakilySendTheOtherTeamOur(JSON.stringify({ secureLine.sneakilySendTheOtherTeamOur(
"type": "ADD", JSON.stringify({
"identifier": id, type: "ADD",
"weight": point[2], identifier: id,
"colour": [R, G, B], weight: point[2],
"start": [point[0], point[1]] colour: [R, G, B],
})); start: [point[0], point[1]],
upTo++; }),
)
upTo++
} }
let batch = [] const batch = []
for (; upTo !== points.length; upTo++) { for (; upTo !== points.length; upTo++) {
const point = points[upTo]; const point = points[upTo]
batch.push([point[0], point[1]]); batch.push([point[0], point[1]])
} }
if (batch.length !== 0) { if (batch.length !== 0) {
secureLine.sneakilySendTheOtherTeamOur(JSON.stringify({ secureLine.sneakilySendTheOtherTeamOur(
"type": "APPEND", JSON.stringify({
"identifier": id, type: "APPEND",
"points": batch identifier: id,
})); points: batch,
}),
)
} }
divulgedUpTo.set(id, upTo); divulgedUpTo.set(id, upTo)
}), }),
room.addEventListener(
"removedIntervalsChange",
({ detail: { id, intervals, points } }) => {
const currentIntervals = combineErasureIntervals(
room.erasureIntervals[id] || {},
intervals,
)
room.erasureIntervals[id] = currentIntervals
const mapping = pointPresenceMap.get(id)
if (mapping === undefined || mapping.length != points.length) {
pointPresenceMap.set(id, Array(points.length).fill(true))
}
for (const point in currentIntervals) {
deletePoint(id, parseInt(point))
}
},
)
room.addEventListener( secureLine.addEventListener("stanza", ({ detail: stanza }) => {
"removedIntervalsChange", const content = stanza.children[0]
({ detail: { id, intervals, points } }) => { if (content.name !== "body") {
const currentIntervals = combineErasureIntervals( return
room.erasureIntervals[id] || {}, }
intervals,
)
room.erasureIntervals[id] = currentIntervals; const message = JSON.parse(content.children[0])
if (divulgedUpTo.get(message.identifier) !== undefined) {
// Don't play ourselves
return
}
if (pointPresenceMap.get(id) === undefined) { const ourID = pathIDsByXCDPIdentifier.get(message.identifier)
pointPresenceMap.set(id, Array(points.length).fill(true)) if (message.type === "ADD") {
if (ourID !== undefined) {
return
} }
for (const point in currentIntervals) { pathIDsByXCDPIdentifier.set(
deletePoint(id, parseInt(point)) message.identifier,
room.addPath([message.start[0], message.start[1], 5, "#000000"]),
)
} else if (message.type === "APPEND") {
if (ourID === undefined) {
// They're trying to hack us with an ID that wasn't added
// TODO: initiate DDOS against them in retaliation
return
} }
},
) for (const index in message.points) {
const point = message.points[index]
room.extendPath(ourID, [point[0], point[1], 5, "#000000"])
}
}
})
} }
const deletePoint = (lineID, offset) => { const deletePoint = (lineID, offset) => {
...@@ -110,33 +154,39 @@ const deletePoint = (lineID, offset) => { ...@@ -110,33 +154,39 @@ const deletePoint = (lineID, offset) => {
return return
} }
if (offset > 0 && bLine[offset - 1] && offset < (bLine.length - 1) && bLine[offset + 1]) { if (
secureLine.sneakilySendTheOtherTeamOur(JSON.stringify({ offset > 0 &&
"type": "BIFURCATE", bLine[offset - 1] &&
"identifier": lineID, offset < bLine.length - 1 &&
"start_offset": offset, bLine[offset + 1]
"end_offset": offset ) {
})) secureLine.sneakilySendTheOtherTeamOur(
JSON.stringify({
type: "BIFURCATE",
identifier: lineID,
start_offset: offset,
end_offset: offset,
}),
)
} }
secureLine.sneakilySendTheOtherTeamOur(JSON.stringify({ secureLine.sneakilySendTheOtherTeamOur(
"type": "DELETE", JSON.stringify({
"identifier": lineID, type: "DELETE",
"offset": offset identifier: lineID,
})) offset: offset,
}),
)
bLine[offset] = false bLine[offset] = false
} }
const tryRoomConnect = async (roomID) => { const tryRoomConnect = async (roomID) => {
return await connect(roomID) return await connect(roomID)
.then(onRoomConnect) .then(onRoomConnect)
.catch((err) => alert(`Error connecting to a room:\n${err}`)) .catch((err) => alert(`Error connecting to a room:\n${err}`))
} }
const pathIDsByPointerID = new Map()
window.addEventListener("unload", () => { window.addEventListener("unload", () => {
if (room) { if (room) {
room.disconnect() room.disconnect()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment