Fix 2
This commit is contained in:
parent
95cee18537
commit
e0a15d5333
157
2.ts
157
2.ts
|
@ -1,108 +1,71 @@
|
||||||
import { readLines } from "https://deno.land/std@0.157.0/io/buffer.ts";
|
import { BufReader } from "https://deno.land/std@0.157.0/io/buffer.ts";
|
||||||
|
import { ByteSet } from "https://deno.land/x/bytes@1.0.3/mod.ts";
|
||||||
|
|
||||||
|
const QUERY_SIZE = 9;
|
||||||
const PORT = 5588;
|
const PORT = 5588;
|
||||||
console.log(`Starting TCP listener on on 0.0.0.0:${PORT}`);
|
|
||||||
|
|
||||||
const clients = new Map<Deno.Conn, string>();
|
const listener = Deno.listen({ port: 5588 });
|
||||||
|
|
||||||
const tEnc = new TextEncoder();
|
console.log(`Listening on port ${PORT}`);
|
||||||
|
|
||||||
async function chatSession(conn: Deno.Conn) {
|
for await (const conn of listener) {
|
||||||
try {
|
|
||||||
let myNick: string | null = null;
|
|
||||||
await sendPrompt(conn);
|
|
||||||
for await (const line of readLines(conn)) {
|
|
||||||
console.debug("Received line:", line);
|
|
||||||
const message = line.trim();
|
|
||||||
if (myNick == null) {
|
|
||||||
if (isLegalNick(message)) {
|
|
||||||
myNick = message;
|
|
||||||
await join(myNick, conn);
|
|
||||||
} else {
|
|
||||||
console.error("Illegal nick:", message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const conns: Deno.Conn[] = [];
|
|
||||||
for (const themConn of clients.keys()) {
|
|
||||||
if (themConn != conn) conns.push(themConn);
|
|
||||||
}
|
|
||||||
await send(conns, `[${myNick}] ${message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (clients.has(conn)) {
|
|
||||||
try {
|
|
||||||
await disconnect(conn);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to disconnect:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (conn.writable) {
|
|
||||||
send(conn, "You are being disconnected...");
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to send disconnect notice:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to close connection:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function send(
|
|
||||||
connsArg: Deno.Conn | Array<Deno.Conn>,
|
|
||||||
text: string,
|
|
||||||
) {
|
|
||||||
const conns = !Array.isArray(connsArg) ? [connsArg] : connsArg;
|
|
||||||
const messages: Promise<number>[] = [];
|
|
||||||
const bytes = tEnc.encode(text + "\n");
|
|
||||||
conns.forEach((conn) => messages.push(conn.write(bytes)));
|
|
||||||
return await Promise.all(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
const broadcast = async (text: string) => await send([...clients.keys()], text);
|
|
||||||
|
|
||||||
const LEGAL_NICK_REGEXP = /^[a-z0-9]+$/i;
|
|
||||||
const isLegalNick = (nick: string) => {
|
|
||||||
console.debug(
|
|
||||||
`Checking nick: ${nick} (Bytes: ${tEnc.encode(nick)})`,
|
|
||||||
);
|
|
||||||
return LEGAL_NICK_REGEXP.exec(nick) != null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendPrompt = async (conn: Deno.Conn) => {
|
|
||||||
console.debug("Sending prompt...");
|
|
||||||
return await send(conn, "Who you be?");
|
|
||||||
};
|
|
||||||
|
|
||||||
async function join(myNick: string, conn: Deno.Conn) {
|
|
||||||
const userList: string[] = [];
|
|
||||||
clients.forEach((nick, _) => userList.push(nick));
|
|
||||||
await broadcast(`* ${myNick} joined`);
|
|
||||||
clients.set(conn, myNick);
|
|
||||||
await send(conn, `* users: ${userList.join(", ")}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function disconnect(conn: Deno.Conn) {
|
|
||||||
const myNick = clients.get(conn);
|
|
||||||
clients.delete(conn);
|
|
||||||
await broadcast(`* ${myNick} left`);
|
|
||||||
}
|
|
||||||
|
|
||||||
for await (const conn of Deno.listen({ port: PORT })) {
|
|
||||||
console.log("Connection established:", conn.remoteAddr);
|
console.log("Connection established:", conn.remoteAddr);
|
||||||
try {
|
try {
|
||||||
chatSession(conn);
|
meansToAnEnd(conn);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(conn.remoteAddr, e);
|
||||||
"Exception occurred during chat session:",
|
|
||||||
conn.remoteAddr,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
console.log("Connection closed:", conn.remoteAddr);
|
console.log("Connection closed:", conn.remoteAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function meansToAnEnd(conn: Deno.Conn) {
|
||||||
|
try {
|
||||||
|
const prices = [];
|
||||||
|
for await (const query of queries(conn)) {
|
||||||
|
if (query == null) break;
|
||||||
|
const bs = ByteSet.from(query, "big");
|
||||||
|
const queryChar = String.fromCharCode(bs.read.uint8());
|
||||||
|
const a1 = bs.read.int32();
|
||||||
|
const a2 = bs.read.int32();
|
||||||
|
if (queryChar == "I") {
|
||||||
|
prices.push([a1, a2]);
|
||||||
|
} else if (queryChar == "Q") {
|
||||||
|
let numMatches = 0;
|
||||||
|
let sum = 0;
|
||||||
|
for (const [ts, price] of prices) {
|
||||||
|
if (ts < a1 || ts > a2) continue;
|
||||||
|
numMatches++;
|
||||||
|
sum += price;
|
||||||
|
}
|
||||||
|
let result = Math.floor(sum / numMatches);
|
||||||
|
if (isNaN(result)) result = 0;
|
||||||
|
console.log(
|
||||||
|
conn.remoteAddr,
|
||||||
|
`Result for ${prices.length} prices: ${sum} / ${numMatches} = ${result}`,
|
||||||
|
);
|
||||||
|
const response = new ByteSet(4, "big");
|
||||||
|
response.write.int32(result);
|
||||||
|
conn.write(response.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("Done!");
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error processing query:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function queries(conn: Deno.Conn) {
|
||||||
|
return {
|
||||||
|
async *[Symbol.asyncIterator]() {
|
||||||
|
const b = new Uint8Array(9);
|
||||||
|
const reader = new BufReader(conn, QUERY_SIZE);
|
||||||
|
try {
|
||||||
|
while (await reader.readFull(b) != null) {
|
||||||
|
yield b;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error receiving query:", err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue