From d59883d5e16cce2911fb59101887861768cb5762 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 6 Oct 2022 12:47:45 -0500 Subject: [PATCH] Problem 4 --- main.ts | 121 +++++++++----------------------------------------------- 1 file changed, 19 insertions(+), 102 deletions(-) diff --git a/main.ts b/main.ts index 9fa8c7a..e052fbe 100644 --- a/main.ts +++ b/main.ts @@ -1,108 +1,25 @@ -import { readLines } from "https://deno.land/std@0.157.0/io/buffer.ts"; - const PORT = 5588; -console.log(`Starting TCP listener on on 0.0.0.0:${PORT}`); - -const clients = new Map(); +console.log(`Starting UDP listener on port ${PORT}`); +const tDec = new TextDecoder(); const tEnc = new TextEncoder(); -async function chatSession(conn: Deno.Conn) { - 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); +const reservedData: Record = { version: "KeyVal 1.0" }; +const data = new Map(); + +const listener = Deno.listenDatagram({ port: PORT, transport: "udp" }); + +for await (const [bytes, addr] of listener) { + const message = tDec.decode(bytes).trim(); + console.debug("Datagram Received from:", addr, message); + if (message.includes("=")) { + const [key, val] = message.split("=", 1); + console.debug(`Setting ${key} to ${val}`); + if (!(key in reservedData)) data.set(key, val); + } else { + const value = reservedData[message] || data.get(message) || ""; + const bytes = tEnc.encode(`${message}=${value}`); + console.debug(`Sending ${message}=${value}`); + await listener.send(bytes, addr); } } - -async function send( - connsArg: Deno.Conn | Array, - text: string, -) { - const conns = !Array.isArray(connsArg) ? [connsArg] : connsArg; - const messages: Promise[] = []; - 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); - try { - chatSession(conn); - } catch (e) { - console.error( - "Exception occurred during chat session:", - conn.remoteAddr, - e, - ); - } - console.log("Connection closed:", conn.remoteAddr); -}