105 lines
3.1 KiB
Python
105 lines
3.1 KiB
Python
__author__ = "Kieran Osborne"
|
|
__version__ = "0.0.1"
|
|
__status__ = "Development"
|
|
|
|
if (__name__ == "__main__"):
|
|
import config
|
|
import traceback
|
|
import socket as network
|
|
import selectors
|
|
import message
|
|
|
|
class User:
|
|
def __init__(self, user_socket: network.socket):
|
|
self.socket = user_socket
|
|
self.connection, self.address = user_socket.accept()
|
|
self.selector = selectors.DefaultSelector()
|
|
|
|
print("Accepted connection from", self.address)
|
|
self.connection.setblocking(False)
|
|
|
|
def close(self):
|
|
self.selector.close()
|
|
self.socket.close()
|
|
|
|
def read(self):
|
|
try:
|
|
# Should be ready to read
|
|
data = self.socket.recv(4096)
|
|
except BlockingIOError:
|
|
# Resource temporarily unavailable (errno EWOULDBLOCK)
|
|
pass
|
|
else:
|
|
if data:
|
|
print(message.deserialize(data))
|
|
else:
|
|
raise RuntimeError("Peer closed.")
|
|
|
|
def write(self):
|
|
pass
|
|
|
|
def run(self):
|
|
try:
|
|
while True:
|
|
events = self.selector.select(timeout=None)
|
|
|
|
for (key, mask) in events:
|
|
try:
|
|
if (mask & selectors.EVENT_READ):
|
|
self.read()
|
|
|
|
elif (mask & selectors.EVENT_WRITE):
|
|
self.write()
|
|
|
|
except Exception:
|
|
print(f"Exception raised on {self.address}: {traceback.format_exc()}"),
|
|
self.socket.close()
|
|
|
|
if not self.selector.get_map():
|
|
break
|
|
|
|
except KeyboardInterrupt:
|
|
print("caught keyboard interrupt, exiting")
|
|
|
|
finally:
|
|
self.selector.close()
|
|
|
|
def init():
|
|
address = (config.host, config.port)
|
|
selector = selectors.DefaultSelector()
|
|
|
|
with network.socket(network.AF_INET, network.SOCK_STREAM) as socket:
|
|
# Avoid bind() exception: OSError: [Errno 48] Address already in use
|
|
socket.setsockopt(network.SOL_SOCKET, network.SO_REUSEADDR, 1)
|
|
socket.bind(address)
|
|
socket.listen()
|
|
|
|
print("Listening on", address)
|
|
|
|
socket.setblocking(False)
|
|
selector.register(socket, selectors.EVENT_READ, data=None)
|
|
|
|
users = []
|
|
|
|
try:
|
|
while True:
|
|
events = selector.select(timeout=None)
|
|
|
|
for (key, mask) in events:
|
|
if key.data is None:
|
|
user = User(key.fileobj)
|
|
|
|
users.append(user)
|
|
user.run()
|
|
|
|
except KeyboardInterrupt:
|
|
print("Caught keyboard interrupt, exiting")
|
|
|
|
finally:
|
|
for user in users:
|
|
user.close()
|
|
|
|
selector.close()
|
|
|
|
init()
|