|
|
|
import * as des from './deserializer';
|
|
|
|
import * as send from './send';
|
|
|
|
import * as math from './math';
|
|
|
|
import * as storage from './storage';
|
|
|
|
import * as config from './config';
|
|
|
|
|
|
|
|
import { SESSION, MESSAGE, EVENT } from './enums';
|
|
|
|
import { sessions, desks, queries } from './storage';
|
|
|
|
|
|
|
|
// Session ACKed events up to SN
|
|
|
|
function recv_ack(d, session) {
|
|
|
|
const sn = des.u32(d);
|
|
|
|
|
|
|
|
session.state = SESSION.READY;
|
|
|
|
session.sn = sn;
|
|
|
|
session.sync_attempts = 0;
|
|
|
|
|
|
|
|
if (config.DEBUG_PRINT) console.log(`ack ${sn} in`);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function recv_syn(d, session) {
|
|
|
|
const lsn = des.u32(d);
|
|
|
|
const count = des.u32(d);
|
|
|
|
|
|
|
|
if (config.DEBUG_PRINT) console.log(`syn ${lsn} in, total size = ${d.size}`);
|
|
|
|
|
|
|
|
const we_expect = lsn - session.lsn;
|
|
|
|
const first = count - we_expect;
|
|
|
|
const events = [];
|
|
|
|
|
|
|
|
if (config.DEBUG_PRINT) console.log(`we expect ${we_expect}, count ${count}`);
|
|
|
|
|
|
|
|
for (let i = 0; i < count; ++i) {
|
|
|
|
const event = des.event(d);
|
|
|
|
if (i >= first) {
|
|
|
|
event.desk_id = session.desk_id;
|
|
|
|
event.user_id = session.id;
|
|
|
|
handle_event(session, event);
|
|
|
|
events.push(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
desks[session.desk_id].sn += we_expect;
|
|
|
|
desks[session.desk_id].events.push(...events);
|
|
|
|
session.lsn = lsn;
|
|
|
|
|
|
|
|
storage.queries.update_desk_sn.run({
|
|
|
|
'$id': session.desk_id,
|
|
|
|
'$sn': desks[session.desk_id].sn
|
|
|
|
});
|
|
|
|
|
|
|
|
storage.queries.update_session_lsn.run({
|
|
|
|
'$id': session.id,
|
|
|
|
'$lsn': lsn
|
|
|
|
});
|
|
|
|
|
|
|
|
send.send_ack(session.ws, lsn);
|
|
|
|
send.sync_desk(session.desk_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
function recv_fire(d, session) {
|
|
|
|
const event = des.event(d);
|
|
|
|
|
|
|
|
event.user_id = session.id;
|
|
|
|
|
|
|
|
switch (event.type) {
|
|
|
|
case EVENT.SET_COLOR: {
|
|
|
|
session.color = event.color;
|
|
|
|
|
|
|
|
storage.queries.update_session_color.run({
|
|
|
|
'$id': session.id,
|
|
|
|
'$color': event.color
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case EVENT.SET_WIDTH: {
|
|
|
|
session.width = event.width;
|
|
|
|
|
|
|
|
storage.queries.update_session_width.run({
|
|
|
|
'$id': session.id,
|
|
|
|
'$width': event.width
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const sid in sessions) {
|
|
|
|
const other = sessions[sid];
|
|
|
|
|
|
|
|
if (other.id === session.id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (other.state !== SESSION.READY) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (other.desk_id != session.desk_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
send.send_fire(other.ws, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function handle_event(session, event) {
|
|
|
|
switch (event.type) {
|
|
|
|
case EVENT.STROKE: {
|
|
|
|
const stroke_result = storage.queries.insert_stroke.get({
|
|
|
|
'$width': event.width,
|
|
|
|
'$color': event.color,
|
|
|
|
'$points': event.points
|
|
|
|
});
|
|
|
|
|
|
|
|
event.stroke_id = stroke_result.id;
|
|
|
|
|
|
|
|
storage.queries.insert_event.run({
|
|
|
|
'$type': event.type,
|
|
|
|
'$desk_id': session.desk_id,
|
|
|
|
'$session_id': session.id,
|
|
|
|
'$stroke_id': event.stroke_id,
|
|
|
|
'$image_id': 0,
|
|
|
|
'$x': 0,
|
|
|
|
'$y': 0,
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case EVENT.ERASER:
|
|
|
|
case EVENT.IMAGE:
|
|
|
|
case EVENT.IMAGE_MOVE:
|
|
|
|
case EVENT.UNDO: {
|
|
|
|
storage.queries.insert_event.run({
|
|
|
|
'$type': event.type,
|
|
|
|
'$desk_id': session.desk_id,
|
|
|
|
'$session_id': session.id,
|
|
|
|
'$stroke_id': event.stroke_id || 0,
|
|
|
|
'$image_id': event.image_id || 0,
|
|
|
|
'$x': event.x || 0,
|
|
|
|
'$y': event.y || 0,
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: {
|
|
|
|
console.error('fuck');
|
|
|
|
console.trace();
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function handle_message(ws, d) {
|
|
|
|
if (!(ws.data.session_id in sessions)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const session = sessions[ws.data.session_id];
|
|
|
|
const desk_id = session.desk_id;
|
|
|
|
const message_type = des.u8(d);
|
|
|
|
|
|
|
|
switch (message_type) {
|
|
|
|
case MESSAGE.FIRE: {
|
|
|
|
recv_fire(d, session);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MESSAGE.SYN: {
|
|
|
|
recv_syn(d, session);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MESSAGE.ACK: {
|
|
|
|
recv_ack(d, session);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: {
|
|
|
|
console.error('fuck');
|
|
|
|
console.trace();
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|