Clarify intentional outages from server linking related things
This commit is contained in:
parent
1714010182
commit
7c0c4b0875
1 changed files with 173 additions and 156 deletions
329
server.py
329
server.py
|
@ -1,17 +1,19 @@
|
||||||
#! /usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import os, sys, asyncio, re, signal
|
import os, sys, asyncio, re, signal
|
||||||
from platform import uname
|
from platform import uname
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
from logs import log
|
from logs import log
|
||||||
|
|
||||||
|
|
||||||
class LinksDownException(Exception): ...
|
class LinkDownError(Exception): ...
|
||||||
|
|
||||||
|
|
||||||
|
class FailedLinkError(Exception): ...
|
||||||
|
|
||||||
|
|
||||||
class Globals: ...
|
class Globals: ...
|
||||||
|
|
||||||
|
|
||||||
# The two below lines are a hacky fix for python 3.10 asyncio
|
|
||||||
TimeoutErrors = (TimeoutError, asyncio.exceptions.TimeoutError)
|
TimeoutErrors = (TimeoutError, asyncio.exceptions.TimeoutError)
|
||||||
DisconnectErrors = (ConnectionResetError, BrokenPipeError, IndexError, *TimeoutErrors)
|
DisconnectErrors = (ConnectionResetError, BrokenPipeError, IndexError, *TimeoutErrors)
|
||||||
G = Globals()
|
G = Globals()
|
||||||
|
@ -401,169 +403,179 @@ Please note that this is not network level statistics.\n""".encode(
|
||||||
|
|
||||||
async def connectServer(hostname: str, port: int):
|
async def connectServer(hostname: str, port: int):
|
||||||
global G
|
global G
|
||||||
reader, writer = await asyncio.open_connection(hostname, port)
|
|
||||||
await reader.read(1024)
|
|
||||||
writer.write(f"S2S-{G.remoteID}\n".encode("utf8"))
|
|
||||||
await writer.drain()
|
|
||||||
await reader.read(1024)
|
|
||||||
for client in G.clientsConnected:
|
|
||||||
writer.write(f"{client}\n".encode("utf8"))
|
|
||||||
await writer.drain()
|
|
||||||
resp = raw((await reader.read(1024)).decode("utf8"))
|
|
||||||
if resp.startswith("K"):
|
|
||||||
if G.clientsConnected[client] == G.remoteID:
|
|
||||||
G.killList[client] = True
|
|
||||||
else:
|
|
||||||
G.servers[G.clientsConnected[client]][client] = True
|
|
||||||
writer.write(f"END OF CLIENT LISTING FROM {G.remoteID}\n".encode("utf8"))
|
|
||||||
await writer.drain()
|
|
||||||
rID = raw((await reader.read(16)).decode("utf8"))
|
|
||||||
try:
|
try:
|
||||||
await asyncio.wait_for(reader.read(1024), 0.1)
|
reader, writer = await asyncio.open_connection(hostname, port)
|
||||||
except TimeoutErrors:
|
await reader.read(1024)
|
||||||
pass
|
writer.write(f"S2S-{G.remoteID}\n".encode("utf8"))
|
||||||
if G.servers.get(rID, False) != False:
|
await writer.drain()
|
||||||
writer.close()
|
await reader.read(1024)
|
||||||
await writer.wait_closed()
|
for client in G.clientsConnected:
|
||||||
return
|
writer.write(f"{client}\n".encode("utf8"))
|
||||||
if G.remoteID == rID:
|
|
||||||
writer.close()
|
|
||||||
await writer.wait_closed()
|
|
||||||
return
|
|
||||||
G.msgs.append(log(f"{rID} has linked to the network"))
|
|
||||||
G.servers[rID] = {}
|
|
||||||
writer.write(b"I recieved your remote ID, now awaiting client listing\n")
|
|
||||||
await writer.drain()
|
|
||||||
# recieve client list from the other server
|
|
||||||
while 1:
|
|
||||||
client = raw((await reader.read(1024)).decode("utf8"))
|
|
||||||
if client == f"END OF CLIENT LISTING FROM {rID}":
|
|
||||||
break
|
|
||||||
if client.lower() in G.servers[rID] or client.lower() in G.clientsConnected:
|
|
||||||
writer.write(b"K Client rejected: Already exists\n")
|
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
continue
|
resp = raw((await reader.read(1024)).decode("utf8"))
|
||||||
writer.write(b"I added that client.\n")
|
if resp.startswith("K"):
|
||||||
|
if G.clientsConnected[client] == G.remoteID:
|
||||||
|
G.killList[client] = True
|
||||||
|
else:
|
||||||
|
G.servers[G.clientsConnected[client]][client] = True
|
||||||
|
writer.write(f"END OF CLIENT LISTING FROM {G.remoteID}\n".encode("utf8"))
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
G.msgs.append(log(f"{client} has connected from {rID}"))
|
rID = raw((await reader.read(16)).decode("utf8"))
|
||||||
G.servers[rID][client.lower()] = False
|
try:
|
||||||
for client in G.servers[rID]:
|
await asyncio.wait_for(reader.read(1024), 0.1)
|
||||||
G.clientsConnected[client] = rID
|
except TimeoutErrors:
|
||||||
msgInd = len(G.S2SLogs)
|
pass
|
||||||
try:
|
if G.servers.get(rID, False) != False:
|
||||||
|
writer.close()
|
||||||
|
await writer.wait_closed()
|
||||||
|
return
|
||||||
|
if G.remoteID == rID:
|
||||||
|
writer.close()
|
||||||
|
await writer.wait_closed()
|
||||||
|
return
|
||||||
|
G.msgs.append(log(f"{rID} has linked to the network"))
|
||||||
|
G.servers[rID] = {}
|
||||||
|
writer.write(b"I recieved your remote ID, now awaiting client listing\n")
|
||||||
|
await writer.drain()
|
||||||
|
# recieve client list from the other server
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
client = raw((await reader.read(1024)).decode("utf8"))
|
||||||
rawMsg = await asyncio.wait_for(reader.read(967), 0.1)
|
if client == f"END OF CLIENT LISTING FROM {rID}":
|
||||||
buffer = raw(rawMsg.decode("utf8"))
|
break
|
||||||
match buffer[0]:
|
if client.lower() in G.servers[rID] or client.lower() in G.clientsConnected:
|
||||||
case "S":
|
writer.write(b"K Client rejected: Already exists\n")
|
||||||
G.msgs.extend([log(buffer[2:])])
|
await writer.drain()
|
||||||
writer.write(b"I Mmm... Blueberries\n")
|
continue
|
||||||
case "I":
|
writer.write(b"I added that client.\n")
|
||||||
pass
|
await writer.drain()
|
||||||
case "+":
|
G.msgs.append(log(f"{client} has connected from {rID}"))
|
||||||
cName = buffer[2:]
|
G.servers[rID][client.lower()] = False
|
||||||
if cName.lower() not in G.clientsConnected:
|
for client in G.servers[rID]:
|
||||||
G.msgs.append(log(f"{cName} has connected from {rID}"))
|
G.clientsConnected[client] = rID
|
||||||
G.S2SLogs.append(("+", cName, rID))
|
msgInd = len(G.S2SLogs)
|
||||||
G.servers[rID][cName.lower()] = False
|
try:
|
||||||
G.clientsConnected[cName.lower()] = rID
|
while 1:
|
||||||
writer.write(b"I Mmm... Pineapples\n")
|
try:
|
||||||
else:
|
rawMsg = await asyncio.wait_for(reader.read(967), 0.1)
|
||||||
writer.write(f"K {cName}\n".encode("utf8"))
|
buffer = raw(rawMsg.decode("utf8"))
|
||||||
case "-":
|
match buffer[0]:
|
||||||
cName = buffer[2:]
|
case "S":
|
||||||
if G.clientsConnected.get(cName.lower(), None) == rID:
|
G.msgs.extend([log(buffer[2:])])
|
||||||
G.msgs.append(log(f"{cName} has disconnected from {rID}"))
|
writer.write(b"I Mmm... Blueberries\n")
|
||||||
del G.servers[rID][cName.lower()]
|
case "I":
|
||||||
del G.clientsConnected[cName.lower()]
|
pass
|
||||||
G.S2SLogs.append(("-", cName, rID))
|
case "+":
|
||||||
else:
|
cName = buffer[2:]
|
||||||
|
if cName.lower() not in G.clientsConnected:
|
||||||
|
G.msgs.append(log(f"{cName} has connected from {rID}"))
|
||||||
|
G.S2SLogs.append(("+", cName, rID))
|
||||||
|
G.servers[rID][cName.lower()] = False
|
||||||
|
G.clientsConnected[cName.lower()] = rID
|
||||||
|
writer.write(b"I Mmm... Pineapples\n")
|
||||||
|
else:
|
||||||
|
writer.write(f"K {cName}\n".encode("utf8"))
|
||||||
|
case "-":
|
||||||
|
cName = buffer[2:]
|
||||||
|
if G.clientsConnected.get(cName.lower(), None) == rID:
|
||||||
|
G.msgs.append(
|
||||||
|
log(f"{cName} has disconnected from {rID}")
|
||||||
|
)
|
||||||
|
del G.servers[rID][cName.lower()]
|
||||||
|
del G.clientsConnected[cName.lower()]
|
||||||
|
G.S2SLogs.append(("-", cName, rID))
|
||||||
|
else:
|
||||||
|
writer.write(
|
||||||
|
f"S Your server is LYING about who is connected to it. - {G.remoteID}, a fellow server\n".encode(
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case "M":
|
||||||
|
cName = buffer[2:].split("|", 1)[0]
|
||||||
|
message = buffer[2:].split("|", 1)[1]
|
||||||
|
G.msgs.append(log(f" {cName}: {message}"))
|
||||||
|
G.S2SLogs.append(("M", (cName, message), rID))
|
||||||
writer.write(
|
writer.write(
|
||||||
f"S Your server is LYING about who is connected to it. - {G.remoteID}, a fellow server\n".encode(
|
b"I Get these damn heretic ghost clients out of my store so i can buy my cult candles in peace.\n"
|
||||||
|
)
|
||||||
|
case "A":
|
||||||
|
cName = buffer[2:].split("|", 1)[0]
|
||||||
|
message = buffer[2:].split("|", 1)[1]
|
||||||
|
G.S2SLogs.append(("A", (cName, message), rID))
|
||||||
|
G.msgs.append(log(f"* {cName} {message}"))
|
||||||
|
writer.write(b"I Mmm... Strawberries\n")
|
||||||
|
case "Q":
|
||||||
|
break
|
||||||
|
case "K":
|
||||||
|
cName = buffer[2:]
|
||||||
|
if G.clientsConnected[cName.lower()] == G.remoteID:
|
||||||
|
G.killList[cName.lower()] = True
|
||||||
|
else:
|
||||||
|
G.servers[G.clientsConnected[cName.lower()]][
|
||||||
|
cName.lower()
|
||||||
|
] = True
|
||||||
|
writer.write(b"I Mmm... Blood\n")
|
||||||
|
case _:
|
||||||
|
writer.write(
|
||||||
|
f"S Your server is doing drugs over here, sending me bullshit messages man - {G.remoteID}, A fellow server\n".encode(
|
||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
case "M":
|
log(
|
||||||
cName = buffer[2:].split("|", 1)[0]
|
f"Recieved invalid message ({buffer}) from {sName}",
|
||||||
message = buffer[2:].split("|", 1)[1]
|
"WARN",
|
||||||
G.msgs.append(log(f" {cName}: {message}"))
|
|
||||||
G.S2SLogs.append(("M", (cName, message), rID))
|
|
||||||
writer.write(
|
|
||||||
b"I Get these damn heretic ghost clients out of my store so i can buy my cult candles in peace.\n"
|
|
||||||
)
|
|
||||||
case "A":
|
|
||||||
cName = buffer[2:].split("|", 1)[0]
|
|
||||||
message = buffer[2:].split("|", 1)[1]
|
|
||||||
G.S2SLogs.append(("A", (cName, message), rID))
|
|
||||||
G.msgs.append(log(f"* {cName} {message}"))
|
|
||||||
writer.write(b"I Mmm... Strawberries\n")
|
|
||||||
case "Q":
|
|
||||||
break
|
|
||||||
case "K":
|
|
||||||
cName = buffer[2:]
|
|
||||||
if G.clientsConnected[cName.lower()] == G.remoteID:
|
|
||||||
G.killList[cName.lower()] = True
|
|
||||||
else:
|
|
||||||
G.servers[G.clientsConnected[cName.lower()]][
|
|
||||||
cName.lower()
|
|
||||||
] = True
|
|
||||||
writer.write(b"I Mmm... Blood\n")
|
|
||||||
case _:
|
|
||||||
writer.write(
|
|
||||||
f"S Your server is doing drugs over here, sending me bullshit messages man - {G.remoteID}, A fellow server\n".encode(
|
|
||||||
"utf8"
|
|
||||||
)
|
)
|
||||||
)
|
await writer.drain()
|
||||||
log(f"Recieved invalid message ({buffer}) from {sName}", "WARN")
|
except TimeoutErrors:
|
||||||
await writer.drain()
|
pass
|
||||||
except TimeoutErrors:
|
if any(G.servers[rID].values()):
|
||||||
pass
|
for name in G.servers[rID]:
|
||||||
if any(G.servers[rID].values()):
|
if G.servers[rID][name]:
|
||||||
for name in G.servers[rID]:
|
writer.write(f"K {name}\n".encode("utf8"))
|
||||||
if G.servers[rID][name]:
|
await writer.drain()
|
||||||
writer.write(f"K {name}\n".encode("utf8"))
|
G.servers[rID][name] = False
|
||||||
await writer.drain()
|
while msgInd < len(G.S2SLogs):
|
||||||
G.servers[rID][name] = False
|
type, data, server = G.S2SLogs[msgInd]
|
||||||
while msgInd < len(G.S2SLogs):
|
if server != rID:
|
||||||
type, data, server = G.S2SLogs[msgInd]
|
match type:
|
||||||
if server != rID:
|
case "A":
|
||||||
match type:
|
nick, msg = data
|
||||||
case "A":
|
writer.write(f"A {nick}|{msg}\n".encode("utf8"))
|
||||||
nick, msg = data
|
case "M":
|
||||||
writer.write(f"A {nick}|{msg}\n".encode("utf8"))
|
nick, msg = data
|
||||||
case "M":
|
writer.write(f"M {nick}|{msg}\n".encode("utf8"))
|
||||||
nick, msg = data
|
case "+":
|
||||||
writer.write(f"M {nick}|{msg}\n".encode("utf8"))
|
writer.write(f"+ {data}\n".encode("utf8"))
|
||||||
case "+":
|
case "-":
|
||||||
writer.write(f"+ {data}\n".encode("utf8"))
|
writer.write(f"- {data}\n".encode("utf8"))
|
||||||
case "-":
|
case _:
|
||||||
writer.write(f"- {data}\n".encode("utf8"))
|
pass
|
||||||
case _:
|
await writer.drain()
|
||||||
pass
|
msgInd += 1
|
||||||
await writer.drain()
|
if G.cwlgd:
|
||||||
msgInd += 1
|
raise LinkDownError
|
||||||
if G.cwlgd:
|
await writer.drain()
|
||||||
raise LinksDownException
|
writer.close()
|
||||||
await writer.drain()
|
await writer.wait_closed()
|
||||||
writer.close()
|
for cName in G.servers[rID]:
|
||||||
await writer.wait_closed()
|
G.msgs.append(log(f"{cName}'s server is going down"))
|
||||||
for cName in G.servers[rID]:
|
|
||||||
G.msgs.append(log(f"{cName}'s server is going down"))
|
|
||||||
del G.clientsConnected[cName.lower()]
|
|
||||||
del G.servers[rID]
|
|
||||||
G.msgs.append(log(f"{rID} has de-linked from the network"))
|
|
||||||
except DisconnectErrors:
|
|
||||||
if G.cwlgd:
|
|
||||||
raise LinksDownException
|
|
||||||
for cName in G.servers[rID]:
|
|
||||||
G.msgs.append(log(f"{cName}'s server is going down"))
|
|
||||||
try:
|
|
||||||
del G.clientsConnected[cName.lower()]
|
del G.clientsConnected[cName.lower()]
|
||||||
except Exception:
|
del G.servers[rID]
|
||||||
pass
|
G.msgs.append(log(f"{rID} has de-linked from the network"))
|
||||||
del G.servers[rID]
|
except DisconnectErrors:
|
||||||
G.msgs.append(log(f"{rID} has de-linked from the network"))
|
if G.cwlgd:
|
||||||
|
raise LinkDownError
|
||||||
|
for cName in G.servers[rID]:
|
||||||
|
G.msgs.append(log(f"{cName}'s server is going down"))
|
||||||
|
try:
|
||||||
|
del G.clientsConnected[cName.lower()]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
del G.servers[rID]
|
||||||
|
G.msgs.append(log(f"{rID} has de-linked from the network"))
|
||||||
|
except OSError as E:
|
||||||
|
log("OSError: " + str(E), "ERROR")
|
||||||
|
if G.cwlgd:
|
||||||
|
raise FailedLinkError
|
||||||
|
|
||||||
|
|
||||||
async def runServer(address: str, port: int):
|
async def runServer(address: str, port: int):
|
||||||
|
@ -578,6 +590,11 @@ async def runServer(address: str, port: int):
|
||||||
try:
|
try:
|
||||||
links.append(G.event.wait())
|
links.append(G.event.wait())
|
||||||
await asyncio.gather(*links)
|
await asyncio.gather(*links)
|
||||||
|
except LinkDownError:
|
||||||
|
G.msgs.append(log("Lost a server link, going down", "FATAL")[1:])
|
||||||
|
crash = True
|
||||||
|
except FailedLinkError:
|
||||||
|
G.msgs.append(log("Failed to establish a server link, going down", "FATAL")[1:])
|
||||||
except Exception:
|
except Exception:
|
||||||
crash = True
|
crash = True
|
||||||
G.msgs.append(log("Server crash", "FATAL")[1:])
|
G.msgs.append(log("Server crash", "FATAL")[1:])
|
||||||
|
|
Loading…
Reference in a new issue