Advertisement
LEGEND2004

Server

Oct 7th, 2023 (edited)
1,253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.49 KB | None | 0 0
  1. import asyncio
  2. import random
  3. from enum import Enum
  4.  
  5. class Options(Enum):
  6.     CREATE = 1
  7.     SELECT = 2
  8.  
  9. clients = {}  # {'id': {'name': "bob", 'writer': <writer>, 'chatroom_id': "1"}}
  10. chatrooms = {
  11.     'default_chatroom_id': "test"
  12. }  # {'chatroom_id': 'chatroom_name'}
  13. header = 1024
  14. ip, port = 'localhost', 8888
  15.  
  16. # Define a simple XOR-based encryption and decryption function
  17. def simple_xor_encrypt(message, key):
  18.     encrypted_message = bytearray()
  19.     for char in message.encode():
  20.         encrypted_char = char ^ key
  21.         encrypted_message.append(encrypted_char)
  22.     return encrypted_message.decode()
  23.  
  24. def simple_xor_decrypt(encrypted_message, key):
  25.     decrypted_message = bytearray()
  26.     for char in encrypted_message.encode():
  27.         decrypted_char = char ^ key
  28.         decrypted_message.append(decrypted_char)
  29.     return decrypted_message.decode()
  30.  
  31. async def send_message(writer, message, key):
  32.     encrypted_message = simple_xor_encrypt(message, key)
  33.     writer.write(encrypted_message.encode())
  34.     await writer.drain()
  35.  
  36. class Client:
  37.     def __init__(self, writer="", reader=""):
  38.         self.id = "usr" + str(random.random())
  39.         self.writer = writer
  40.         self.reader = reader
  41.         self.name = ""
  42.         self.chatroom_id = ""
  43.         self.client_address = writer.get_extra_info('peername')
  44.         print(f"New connection from {self.client_address}")
  45.  
  46.     def get_user_profile(self):
  47.         return {'name': self.name, 'chatroom_id': self.chatroom_id, 'writer': self.writer}
  48.  
  49.     async def broadcast_to_all(self, message, key):
  50.         for user_id, values in clients.items():
  51.             if user_id != self.id:
  52.                 await send_message(values['writer'], f"{message}", key)
  53.  
  54.     async def multicast_to_chat(self, message, key):
  55.         for user_id, values in clients.items():
  56.             if user_id != self.id and values['chatroom_id'] == self.chatroom_id:
  57.                 await send_message(values['writer'], f"{message}", key)
  58.  
  59.     async def send_message(self, message, key):
  60.         encrypted_message = simple_xor_encrypt(message, key)
  61.         self.writer.write(encrypted_message.encode())
  62.         await self.writer.drain()
  63.  
  64.     async def receive_message(self, key):
  65.         data = await self.reader.read(header)
  66.         decrypted_message = simple_xor_decrypt(data.decode(), key)
  67.         return decrypted_message.strip()
  68.  
  69.     async def client_req_and_res(self, message, key):
  70.         await self.send_message(message, key)
  71.         return await self.receive_message(key)
  72.  
  73.     async def remove_client(self, key):
  74.         del clients[self.id]
  75.         await self.multicast_to_chat(f"{self.name} has left the chat!\n", key)
  76.         self.writer.close()
  77.         await self.writer.wait_closed()
  78.         print(f"Connection closed for {self.client_address}")
  79.  
  80.     async def choose_name(self, key):
  81.         self.name = await self.client_req_and_res("Welcome to the chatroom! Please enter your name: \n", key)
  82.         print(f"{self.name} has joined the server")
  83.  
  84.     async def choose_chat(self, key):
  85.         option = ""
  86.         while option not in [Options.CREATE, Options.SELECT]:
  87.             chatroom_names = "\n".join(chatrooms.values())
  88.             option = await self.client_req_and_res(f"\n1. Create a Chatroom\n2. Select a Chatroom:\n{chatroom_names}\n", key)
  89.             try:
  90.                 option = Options(int(option))  # Convert user input to enum
  91.             except ValueError:
  92.                 option = None
  93.             print(f"{option} is chosen")
  94.         while True:
  95.             if option == Options.CREATE:
  96.                 chatroom_name = await self.client_req_and_res("Enter the name of a new chatroom: ", key)
  97.                 print(f"{chatroom_name} chatroom is created")
  98.                 self.chatroom_id = "cht" + str(random.random())
  99.                 chatrooms[self.chatroom_id] = chatroom_name
  100.                 break
  101.             elif option == Options.SELECT:
  102.                 chatroom_name = await self.client_req_and_res("Enter the name of a chatroom: ", key)
  103.                 self.chatroom_id = find_id_by_name(chatroom_name, chatrooms)
  104.                 if not self.chatroom_id:
  105.                     continue
  106.                 break
  107.         await self.multicast_to_chat(f"\n{self.name} has joined the chat!\n", key)
  108.         print(f"{self.chatroom_id} chatroom is accessed on the server")
  109.  
  110.     async def chat_with_others_in_room(self, key):
  111.         while True:
  112.             data = await self.reader.read(header)
  113.             if data == b'\r\n':
  114.                 continue  # Skip empty messages
  115.             decrypted_message = simple_xor_decrypt(data.decode(), key)
  116.             message = f"{self.name}| {decrypted_message}"
  117.             await self.multicast_to_chat(message, key)
  118.  
  119. async def handle_client(reader, writer):
  120.     client = Client(writer, reader)
  121.     await client.choose_name(encryption_key)
  122.     await client.choose_chat(encryption_key)
  123.     clients[client.id] = client.get_user_profile()
  124.     try:
  125.         await client.chat_with_others_in_room(encryption_key)
  126.     except asyncio.CancelledError:
  127.         pass
  128.     except Exception as e:
  129.         print(f"Error handling client {client.name}: {e}")
  130.     finally:
  131.         await client.remove_client(encryption_key)
  132.         del client
  133.  
  134. async def main():
  135.     server = await asyncio.start_server(handle_client, ip, port)
  136.     async with server:
  137.         await server.serve_forever()
  138.  
  139. if __name__ == "__main__":
  140.     encryption_key = 42  # Replace with your own encryption key
  141.     asyncio.run(main())
  142.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement