You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.0 KiB
130 lines
3.0 KiB
import * as des from './deserializer'; |
|
import * as send from './send'; |
|
import * as math from './math'; |
|
import * as storage from './storage'; |
|
|
|
import { SESSION, MESSAGE, EVENT } from './enums'; |
|
import { sessions, desks } 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; |
|
|
|
console.log(`ack ${sn} in`); |
|
} |
|
|
|
function handle_event(session, event) { |
|
switch (event.type) { |
|
case EVENT.STROKE: { |
|
event.stroke_id = math.fast_random32(); |
|
storage.put_stroke(event.stroke_id, session.desk_id, event.points, event.width, event.color); |
|
storage.put_event(event); |
|
break; |
|
} |
|
|
|
case EVENT.IMAGE: |
|
case EVENT.UNDO: { |
|
storage.put_event(event); |
|
break; |
|
} |
|
|
|
default: { |
|
console.error('fuck'); |
|
console.trace(); |
|
process.exit(1); |
|
} |
|
} |
|
} |
|
|
|
async function recv_syn(d, session) { |
|
const padding = des.u8(d); |
|
const lsn = des.u32(d); |
|
const count = des.u32(d); |
|
|
|
console.log(`syn ${lsn} in, total size = ${d.size}`); |
|
|
|
const we_expect = lsn - session.lsn; |
|
const first = count - we_expect; |
|
const events = []; |
|
|
|
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.user_id; |
|
event.stroke_id = null; |
|
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.save_desk_sn(session.desk_id, desks[session.desk_id].sn); |
|
storage.save_session_lsn(session.id, lsn); |
|
|
|
send.send_ack(session.ws, lsn); |
|
send.sync_desk(session.desk_id); |
|
} |
|
|
|
function recv_fire(d, session) { |
|
const event = des.event(d); |
|
|
|
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, session.user_id, event); |
|
} |
|
} |
|
|
|
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); |
|
} |
|
} |
|
}
|
|
|