Browse Source

Fix client disconnection

master
Forest Belton 2 years ago
parent
commit
0820f5a06b
5 changed files with 34 additions and 19 deletions
  1. +3
    -0
      paircd/channel.py
  2. +4
    -17
      paircd/client.py
  3. +1
    -1
      paircd/handler/quit.py
  4. +1
    -1
      paircd/main.py
  5. +25
    -0
      paircd/server.py

+ 3
- 0
paircd/channel.py View File

@ -47,6 +47,9 @@ class Channel:
return f"+{nick}"
return nick
def get_channel_size(self) -> int:
return len(self.clients_by_nick)
def rename_client(self, name: str, new_name: str) -> None:
if name not in self.clients_by_nick:
raise KeyError(f"No client on channel with nick {name}")

+ 4
- 17
paircd/client.py View File

@ -5,7 +5,7 @@ from datetime import datetime
from logging import log, INFO
from typing import Any, Set
from paircd.reply import QUIT, RPL_CREATED, RPL_MYINFO, RPL_WELCOME, RPL_YOURHOST
from paircd.reply import RPL_CREATED, RPL_MYINFO, RPL_WELCOME, RPL_YOURHOST
from paircd.message import Message
@ -48,22 +48,9 @@ class Client:
try:
await self.writer.drain()
except ConnectionResetError:
await self.quit(server, "Connection reset by peer")
async def quit(self, server: Any, msg: str) -> None:
if self.closed:
return
quit_msg = QUIT(msg, prefix=self.id())
for client in server.clients_by_nick.values():
client.write_message(quit_msg)
for channel_name in self.channels:
channel = server.get_channel_by_name(channel_name, create=False)
if channel is None:
continue
channel.remove_client_by_nick(self.nickname)
server.remove_client_by_name(self.nickname)
await self.close()
await server.disconnect_client(
self.nickname, "Connection reset by peer"
)
async def close(self) -> None:
if self.closed:

+ 1
- 1
paircd/handler/quit.py View File

@ -12,4 +12,4 @@ class QuitHandler(CommandHandler):
quit_msg = ""
if len(msg.args) == 1:
quit_msg = msg.args[0]
await client.quit(server, f"Quit: {quit_msg}")
await server.disconnect_client(client.nickname, f"Quit: {quit_msg}")

+ 1
- 1
paircd/main.py View File

@ -23,7 +23,7 @@ async def read_forever(server: Server, client: Client) -> None:
raw_msg = await client.reader.readuntil(b"\r\n")
except IncompleteReadError:
logging.warning("client connection closed", exc_info=exc_info())
await client.quit(server, "Connection reset by peer")
await server.disconnect_client(client.nickname, "Connection reset by peer")
break
msg = parse_message(raw_msg)

+ 25
- 0
paircd/server.py View File

@ -4,6 +4,7 @@ from typing import Dict, Optional
from paircd.client import Client
from paircd.channel import Channel
from paircd.reply import QUIT
@dataclass
@ -33,3 +34,27 @@ class Server:
raise KeyError(f"Client already exists with nick {new_name}")
self.clients_by_nick[new_name] = self.clients_by_nick[name]
del self.clients_by_nick[name]
async def disconnect_client(self, nick: str, quit_msg: str) -> None:
client = self.clients_by_nick[nick]
if client.closed:
return
client.log("is quitting: {quit_msg}")
msg = QUIT(quit_msg, prefix=client.id())
for client in self.clients_by_nick.values():
if client.nickname == nick:
continue
client.write_message(msg)
for channel_name in client.channels:
channel = self.get_channel_by_name(channel_name, create=False)
if channel is None:
continue
channel.remove_client_by_nick(client.nickname)
if channel.get_channel_size() == 0:
del self.channels_by_name[channel_name]
self.remove_client_by_name(client.nickname)
await client.close()

Loading…
Cancel
Save