Setup for future IRC work, add centeralized message parser

This commit is contained in:
Firepup Sixfifty 2024-08-15 04:10:10 +00:00
parent e71b256a3e
commit 6376818b85
Signed by: Firepup650
SSH key fingerprint: SHA256:U0Zp8EhEe3CMqFSrC79CqatzaEiL4sjta80/RSX2XrY

View file

@ -37,6 +37,8 @@ G.outboundLinks = []
G.S2SLogs = [] G.S2SLogs = []
G.cwlgd = False G.cwlgd = False
G.NUL = "\x1e" G.NUL = "\x1e"
G.IRCStats = {"users": {"localMax": 0, "localCurrent": 0, "globalMax": 0, "globalCurrent": 0}, "servers": 0}
G.queue = []
saveLogs = True saveLogs = True
address = "::" address = "::"
# Try to load a message log, if one exists # Try to load a message log, if one exists
@ -113,6 +115,31 @@ if len(G.remoteID) > 16:
G.remoteID = G.remoteID[:15] G.remoteID = G.remoteID[:15]
async def getMessage(reader, localQueue: list, size: int = 0, timeout: float = 0, sanitize: bool = False, _raise: bool = False) -> str:
if not localQueue:
data = ""
if timeout > 0:
if _raise:
data = await asyncio.wait_for(reader.read(size), timeout)
else:
try:
data = await asyncio.wait_for(reader.read(size), timeout)
except TimeoutErrors:
return "" # We should never return nothing, except in this one case.
else:
data = await reader.read(size)
localQueue = data.decode("utf8").strip().split("\r\n")
tmp = localQueue.pop(0)
if sanitize:
tmp = raw(tmp)
if size:
other = tmp[size:]
tmp = tmp[:size]
if other:
localQueue.insert(0, other)
return tmp, localQueue
def raw(string: str) -> str: def raw(string: str) -> str:
s = string.strip() s = string.strip()
s = f"{s!r}"[1:-1].replace("\\\\", "\\") s = f"{s!r}"[1:-1].replace("\\\\", "\\")
@ -135,17 +162,12 @@ async def handleClient(reader, writer):
global G global G
writer.write(b"Please identify yourself. Nick limit is 20 chars.\r\n") writer.write(b"Please identify yourself. Nick limit is 20 chars.\r\n")
await writer.drain() await writer.drain()
name = raw((await reader.read(20)).decode("utf8")) name, localQueue = await getMessage(reader, [], 20, 0, True)
localQueue = []
if len(name) > 20: if len(name) > 20:
name = name[ name = name[
:19 :19
] # Really this is only possible if someone passes raw unicode as a nick, but let's clean it up anyways. ] # Really this is only possible if someone passes raw unicode as a nick, but let's clean it up anyways.
try:
await asyncio.wait_for(
reader.read(), 0.01
) # Silently consume the excess username data
except TimeoutErrors:
pass
if not name: if not name:
writer.write(b"Nice try. Actually set a nick.\r\n") writer.write(b"Nice try. Actually set a nick.\r\n")
await writer.drain() await writer.drain()
@ -158,7 +180,9 @@ async def handleClient(reader, writer):
writer.close() writer.close()
await writer.wait_closed() await writer.wait_closed()
return return
if not name.startswith("S2S-"): if name == "CAP LS 302":
pass # TODO: IRC Logic
elif not name.startswith("S2S-"):
G.clientsConnected[name.lower()] = G.remoteID G.clientsConnected[name.lower()] = G.remoteID
msgIndex = 0 msgIndex = 0
G.uniqueClients += 1 G.uniqueClients += 1
@ -166,8 +190,7 @@ async def handleClient(reader, writer):
G.S2SLogs.append(("+", name, G.remoteID)) G.S2SLogs.append(("+", name, G.remoteID))
while 1: while 1:
try: try:
buffer = await asyncio.wait_for(reader.read(967), 0.1) request, localQueue = await getMessage(reader, localQueue, 967, 0.1, True, True)
request = raw(buffer.decode("utf8"))
response = None response = None
if request.startswith("/mes "): if request.startswith("/mes "):
response = log(f"* {name}'s {request[5:]}") response = log(f"* {name}'s {request[5:]}")
@ -253,7 +276,7 @@ Please note that this is not network level statistics.\r\n""".encode(
msgIndex = 0 msgIndex = 0
writer.write(b"I am awaiting your client listing.\r\n") writer.write(b"I am awaiting your client listing.\r\n")
while 1: while 1:
client = raw((await reader.read(1024)).decode("utf8")) client, localQueue = await getMessage(reader, localQueue, 20, 0, True)
if client == f"END OF CLIENT LISTING FROM {sName}": if client == f"END OF CLIENT LISTING FROM {sName}":
break break
if ( if (
@ -274,7 +297,7 @@ Please note that this is not network level statistics.\r\n""".encode(
for client in G.clientsConnected: for client in G.clientsConnected:
writer.write(f"{client}\r\n".encode("utf8")) writer.write(f"{client}\r\n".encode("utf8"))
await writer.drain() await writer.drain()
resp = raw((await reader.read(1024)).decode("utf8")) resp, localQueue = await getMessage(reader, localQueue, 1024, 0, True)
if resp.startswith("K"): if resp.startswith("K"):
if G.clientsConnected[client] == G.remoteID: if G.clientsConnected[client] == G.remoteID:
G.killList[client] = True G.killList[client] = True
@ -287,8 +310,7 @@ Please note that this is not network level statistics.\r\n""".encode(
msgInd = len(G.S2SLogs) msgInd = len(G.S2SLogs)
while 1: while 1:
try: try:
rawMsg = await asyncio.wait_for(reader.read(967), 0.1) buffer, localQueue = await getMessage(reader, localQueue, 967, 0.1, False, True)
buffer = rawMsg.decode("utf8").strip()
match buffer[0]: match buffer[0]:
case "S": # Server notice case "S": # Server notice
G.msgs.extend([log(buffer[2:])]) G.msgs.extend([log(buffer[2:])])
@ -425,14 +447,14 @@ async def connectServer(hostname: str, port: int):
global G global G
try: try:
reader, writer = await asyncio.open_connection(hostname, port) reader, writer = await asyncio.open_connection(hostname, port)
await reader.read(1024) ext, localQueue = await getMessage(reader, [], 1024)
writer.write(f"S2S-{G.remoteID}\r\n".encode("utf8")) writer.write(f"S2S-{G.remoteID}\r\n".encode("utf8"))
await writer.drain() await writer.drain()
await reader.read(1024) ext, localQueue = await getMessage(reader, [], 1024)
for client in G.clientsConnected: for client in G.clientsConnected:
writer.write(f"{client}\r\n".encode("utf8")) writer.write(f"{client}\r\n".encode("utf8"))
await writer.drain() await writer.drain()
resp = raw((await reader.read(1024)).decode("utf8")) resp, localQueue = await getMessage(reader, [localQueue], 1024)
if resp.startswith("K"): if resp.startswith("K"):
if G.clientsConnected[client] == G.remoteID: if G.clientsConnected[client] == G.remoteID:
G.killList[client] = True G.killList[client] = True
@ -459,7 +481,7 @@ async def connectServer(hostname: str, port: int):
await writer.drain() await writer.drain()
# recieve client list from the other server # recieve client list from the other server
while 1: while 1:
client = raw((await reader.read(1024)).decode("utf8")) client, localQueue = await getMessage(reader, localQueue, 1024, 0, True)
if client == f"END OF CLIENT LISTING FROM {rID}": if client == f"END OF CLIENT LISTING FROM {rID}":
break break
if client.lower() in G.servers[rID] or client.lower() in G.clientsConnected: if client.lower() in G.servers[rID] or client.lower() in G.clientsConnected:
@ -476,8 +498,7 @@ async def connectServer(hostname: str, port: int):
try: try:
while 1: while 1:
try: try:
rawMsg = await asyncio.wait_for(reader.read(1024), 0.1) buffer, localQueue = await getMessage(reader, localQueue, 1024, 0.1, False, True)
buffer = rawMsg.decode("utf8").strip()
match buffer[0]: match buffer[0]:
case "S": case "S":
G.msgs.extend([log(buffer[2:])]) G.msgs.extend([log(buffer[2:])])