async def send_text_message(self, message: str): await self._recreate_connection() await self._send_data(5, Extentions.defstr_to_bytes(message)) code, data = await self._get_data() if code != 5: self._raise_customised_exception(Extentions.bytes_to_defstr(data)[0], code) Logger.log(f"Message to '{self.client_login}' ({self._host}:{self._port}) was successfully sent.")
async def _discover_clients(self, names: List[str]) -> bool: result = False internal_ip = socket.gethostbyname(socket.gethostname()) template_ip = internal_ip[:internal_ip.rfind(".") + 1] for i in range(0, 256): if f"{template_ip}{i}" == internal_ip: continue c = network.ClientToClient("guest", "", f"{template_ip}{i}:3502") Logger.log(f"Trying to find client at {template_ip}{i}:3502...", "client") try: ips = await c.get_IPs(names) Logger.log(f"Client was found at {template_ip}{i}:3502.", "client") for n, i in zip(names, ips): if i[0] == "0.0.0.0": continue if n == "server": if not result: self._server = network.ClientToServer(i[0]) self._database.add_friend("server", *i) result = True elif self._database.get_ip_and_last_time( "server")[1] < i[1]: self._server = network.ClientToServer(i[0]) self._database.update_ip("server", *i) else: self._contacts[n, ip[0], ip[1]].update_ip(*i) except network.ClientToClientException: continue return result
async def delete_user(self, login: str, password: str): await self._recreate_connection() bts_login = Extentions.defstr_to_bytes(login) bts_password = Extentions.defstr_to_bytes(password) await self._send_data(4, bts_login + bts_password) code, data = await self._get_data() if code != 2: self._raise_customised_exception(Extentions.bytes_to_defstr(data)[0], code) Logger.log(f"User '{login}' was successfully deleted.", "client")
async def _recreate_connection(self): try: await super()._recreate_connection() await self._send_data(2, Extentions.defstr_to_bytes(self.login)) code, data = await self._get_data() if code == 2 and (Extentions.bytes_to_defstr(data)[0] == self.client_login or self.login == "guest"): Logger.log(f"Connection with '{self.client_login}' ({self._host}:{self._port}) was established.", "client") return except ClientToServerException as ex: raise ex
async def _recreate_connection(self): if (self.__class__ == _IConnection): self._raise_not_implemented_error() if self._writer is None or not await self._check_connection(1): try: connection = await asyncio.wait_for(asyncio.open_connection(self._host, self._port), 0.25) except (OSError, TimeoutError): self._raise_customised_exception(f"Couldn't (re)create connection with ({self._host}:{self._port}).", 251) return self._reader, self._writer = connection if await self._check_connection(0.25): Logger.log(f"Connection with ({self._host}:{self._port}) was established.", "client") return self._raise_customised_exception(f"Couldn't (re)create connection with ({self._host}:{self._port}).", 251)
async def _discover_server(self) -> bool: internal_ip = socket.gethostbyname(socket.gethostname()) template_ip = internal_ip[:internal_ip.rfind(".") + 1] for i in range(0, 256): c = network.ClientToServer(f"{template_ip}{i}:3501") Logger.log(f"Trying to find server at {template_ip}{i}:3501...", "client") try: await c.get_IPs([]) self._server = c self._database.add_friend("server", f"{template_ip}{i}:3501", datetime.now()) Logger.log(f"Server was found at {template_ip}{i}:3501.", "client") return True except network.ClientToServerException as ex: if ex.code == 251: continue raise ex return False
async def get_IPs(self, logins: List[str]) -> List[Tuple[str, datetime]]: await self._recreate_connection() data = Extentions.int_to_bytes(len(logins)) for i in range(0, len(logins)): data += Extentions.defstr_to_bytes(logins[i]) await self._send_data(3, data) code, data = await self._get_data() if code != 3: self._raise_customised_exception(Extentions.bytes_to_defstr(data)[0], code) result = [] count, data = Extentions.bytes_to_int(data) while count > 0: ip, data = Extentions.bytes_to_defstr(data) time, data = Extentions.bytes_to_defstr(data) if ip == "": result.append((None, None)) else: result.append((ip, datetime.strptime(time, "%H:%M:%S.%f %d.%m.%Y"))) count -= 1 Logger.log("Requested IPs were received.", "client") return result
def main(): Logger.log("", file_only=True) global _database _database = DataBaseServer() _database.init() loop = asyncio.get_event_loop() server_gen = asyncio.start_server(_on_connect, host="0.0.0.0", port=3501) server = loop.run_until_complete(server_gen) # It seems like KeyboardInterrupt handled somewhere in # server() coroutine, then I have to add following line. loop.create_task(_wait_for_interrupt()) _server_endpoint = server.sockets[0].getsockname() Logger.log( f"Listening established on {_server_endpoint[0]}:{_server_endpoint[1]}." ) try: loop.run_forever() except KeyboardInterrupt: Logger.log("Server was stopped by keyboard interrupt.") finally: server.close() loop.close()
def main(): sock: socket = socket() sock.connect(("192.168.43.168", 3501)) Logger.log("Connection with localhost:3501 was established.", "test_client") _send_data(sock, 0) Logger.log("Ping was successfully sent.", "test_client") code, _ = _get_gata(sock) if code != 0: raise TestClientException("Ping wasn't received!") Logger.log("Ping was successfully received.", "test_client") return for i in range(0, 5): bts_login = Extentions.defstr_to_bytes(f"TestUser{i}") bts_password = Extentions.defstr_to_bytes(f"{i + 1}{i}{ (i - 1) * 2}") _send_data(sock, 1, bts_login + bts_password) Logger.log(f"Trying to register TestUser{i}...", "test_client") code, received_data = _get_gata(sock) if code != 1: raise TestClientException(f"TestUser{i} wasn't registered!\n{Extentions.bytes_to_defstr(received_data)}") Logger.log(f"TestUser{i} was successfully registered.", "test_client") bts_login = Extentions.defstr_to_bytes(f"TestUser3") bts_password = Extentions.defstr_to_bytes(f"434") _send_data(sock, 2, bts_login + bts_password) Logger.log("Trying to login as TestUser3...", "test_client") code, received_data = _get_gata(sock) if code != 2: raise TestClientException(f"Login as TestUser3 was failed!\n{Extentions.bytes_to_defstr(received_data)}") Logger.log("Login as TestUser3 was successful.", "test_client") requesting_logins = Extentions.int_to_bytes(4) requesting_logins += Extentions.defstr_to_bytes("TestUser0") requesting_logins += Extentions.defstr_to_bytes("TestUser1") requesting_logins += Extentions.defstr_to_bytes("TestUser2") requesting_logins += Extentions.defstr_to_bytes("TestUser4") _send_data(sock, 3, requesting_logins) Logger.log("IPs was requested.", "test_client") code, received_data = _get_gata(sock) if code != 3: raise TestClientException(f"IP-update request failed!") ips_count, received_data = Extentions.bytes_to_int(received_data) ips_list = ["Following IPs was received:"] while ips_count > 0: requested_ip, received_data = Extentions.bytes_to_defstr(received_data) ips_list.append(f"TestUser{4 - ips_count} : {requested_ip}") ips_count -= 1 Logger.log("\n".join(ips_list), "test_client") _send_data(sock, 4, Extentions.defstr_to_bytes("434")) Logger.log("Trying to delete TestUser3...", "test_client") code, received_data = _get_gata(sock) if code != 4: raise TestClientException(f"Deleting TestUser3 was failed!\n{Extentions.bytes_to_defstr(received_data)}") Logger.log("TestUser3 was successfully deleted.", "test_client") _send_data(sock, 3, Extentions.int_to_bytes(1) + Extentions.defstr_to_bytes("TestUser3")) _, received_data = _get_gata(sock) Logger.log("TestUser3's IP : " + Extentions.bytes_to_defstr(received_data[4:])[0], "test_client") sock.close() Logger.log("Test successfully ended.", "test_client")
async def _on_connect(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): timeout = 5 client_login = None client_endpoint = writer.get_extra_info("peername") client_ip = client_endpoint[0] client_port = client_endpoint[1] Logger.log(f"Accepted connection from {client_ip}:{client_port}.", "client") while True: try: code, data = await self._get_data(reader, timeout) if code == 0: # Ping await self._send_data(writer, 0) Logger.log(f"Ping was sent to {client_ip}:{client_port}.", "client") elif code == 2: # Login received_login, data = Extentions.bytes_to_defstr(data) if len(data) == 0: preferred_port = "3502" else: preferred_port, _ = Extentions.bytes_to_defstr(data) if received_login == "server": await self._send_data(writer, 252, Extentions.defstr_to_bytes("'server' is service login!")) continue client_login = received_login self.update_ip_callback(client_login, client_ip + ":" + preferred_port) await self._send_data(writer, 2, Extentions.defstr_to_bytes(self.login)) timeout = 60 Logger.log(f"Login {client_ip}:{client_port} as '{client_login}' was confirmed.") elif code == 3: # IP updating request login_count, data = Extentions.bytes_to_int(data) ips = Extentions.int_to_bytes(login_count) while login_count > 0: requested_login, data = Extentions.bytes_to_defstr(data) if requested_login == "server": if self._server_endpoint == []: requested_ip = "" requested_time = "" else: requested_ip, requested_time = self._server_endpoint requested_time = requested_time.strftime("%H:%M:%S.%f %d.%m.%Y") requested_line = (Extentions.defstr_to_bytes(requested_ip) + Extentions.defstr_to_bytes(requested_time)) ips += requested_line elif requested_login == self.login: requested_ip = socket.gethostbyname(socket.gethostname()) requested_time = datetime.now().strftime("%H:%M:%S.%f %d.%m.%Y") requested_line = (Extentions.defstr_to_bytes(requested_ip) + Extentions.defstr_to_bytes(requested_time)) ips += requested_line else: tmp = self._database.search_ip_and_last_time(requested_login) if tmp[0] == "0.0.0.0": requested_ip = "" requested_time = "" else: requested_ip, requested_time = tmp requested_time = requested_time.strftime("%H:%M:%S.%f %d.%m.%Y") requested_line = (Extentions.defstr_to_bytes(requested_ip) + Extentions.defstr_to_bytes(requested_time)) ips += requested_line login_count -= 1 await self._send_data(writer, 3, ips) Logger.log(f"Requested IPs was sent to {client_ip}:{client_port}.") elif code == 5: # Text message if client_login is not None and client_login != "guest": self.on_receive_msg_callback(data, client_login, client_ip + ":" + preferred_port) await self._send_data(writer, 5) Logger.log(f"Message from '{client_login}' ({client_ip}:{client_port}) was recieved.") else: await self._send_data(writer, 253, Extentions.defstr_to_bytes("You should login first.")) elif code == 6: # File message pass # TODO: Add handling file messages else: msg, _ = Extentions.bytes_to_str(Extentions.int_to_bytes(code) + data) Logger.log(f"Following message was resieved from {client_ip}:{client_port}:\n{msg}", "client") except ConnectionResetError: Logger.log(f"Connection from {client_ip}:{client_port} closed by peer.", "client") break except TimeoutError: Logger.log(f"Connection from {client_ip}:{client_port} closed by timeout.", "client") break writer.close()
async def listen(self, port: int = 3502): self._server = await asyncio.start_server(self._on_connect_wrapper(), host="0.0.0.0", port=port) # await self._server.start_serving() # REDO Recognize, why it doesn'n work. _endpoint = self._server.sockets[0].getsockname() Logger.log(f"Listening established on {_endpoint[0]}:{_endpoint[1]}.", "client")
async def _on_connect(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): timeout = 5 login = None client_endpoint = writer.get_extra_info("peername") client_ip = client_endpoint[0] if client_ip == "127.0.0.1": client_ip = socket.gethostbyname(socket.gethostname()) client_port = client_endpoint[1] Logger.log(f"Accepted connection from {client_ip}:{client_port}.") while True: try: code, data = await _get_data(reader, timeout) if code == 0: # Ping await _send_data(writer, 0) Logger.log(f"Ping was sent to {client_ip}:{client_port}.") elif code == 1: # Registration received_login, data = Extentions.bytes_to_defstr(data) if received_login == "server" or received_login == "guest": await _send_data( writer, 252, Extentions.defstr_to_bytes( "'server' is service login!")) continue login = received_login pass_hash, data = Extentions.bytes_to_defstr(data) if data == bytes(): preferred_port = "3502" else: preferred_port, _ = Extentions.bytes_to_defstr(data) Logger.log( f"Registration {client_ip}:{client_port} as '{login}'...") if (_database.search_ip_and_last_time(login)[0] != "0.0.0.0"): await _send_data( writer, 254, Extentions.defstr_to_bytes( "This login is already registered.")) Logger.log( f"Registration {client_ip}:{client_port} as '{login}' was refused." ) continue _database.add_client(login, pass_hash, client_ip + ":" + preferred_port) pass_hash = None await _send_data(writer, 1) Logger.log( f"Registration {client_ip}:{client_port} as '{login}' was confirmed." ) timeout = 60 elif code == 2: # Login received_login, data = Extentions.bytes_to_defstr(data) if received_login == "server" or received_login == "guest": await _send_data( writer, 252, Extentions.defstr_to_bytes( "'server' is service login!")) continue login = received_login pass_hash, data = Extentions.bytes_to_defstr(data) if data == bytes(): preferred_port = "3502" else: preferred_port, _ = Extentions.bytes_to_defstr(data) Logger.log(f"Login {client_ip}:{client_port} as '{login}'...") if (_database.search_password(login) != pass_hash): await _send_data( writer, 255, Extentions.defstr_to_bytes("Password is incorrect.")) Logger.log( f"Login {client_ip}:{client_port} as '{login}' was refused." ) continue pass_hash = "" await _send_data(writer, 2) Logger.log( f"Login {client_ip}:{client_port} as '{login}' was confirmed." ) timeout = 60 _database.update_ip(login, client_ip + ":" + preferred_port) elif code == 3: # IP updating request Logger.log(f"IPs was requested by {client_ip}:{client_port}") login_count, data = Extentions.bytes_to_int(data) ips = Extentions.int_to_bytes(login_count) while login_count > 0: requested_login, data = Extentions.bytes_to_defstr(data) tmp = _database.search_ip_and_last_time(requested_login) if tmp[0] == "0.0.0.0": requested_ip = "" requested_time = "" else: requested_ip, requested_time = tmp requested_time = requested_time.strftime( "%H:%M:%S.%f %d.%m.%Y") requested_line = ( Extentions.defstr_to_bytes(requested_ip) + Extentions.defstr_to_bytes(requested_time)) ips += requested_line login_count -= 1 await _send_data(writer, 3, ips) Logger.log( f"Requested IPs was sent to {client_ip}:{client_port}.") elif code == 4: # Delete user request if login is None: await _send_data( writer, 253, Extentions.defstr_to_bytes("You should login first.")) else: pass_hash, _ = Extentions.bytes_to_defstr(data) Logger.log( f"Deleting of '{login}' was requested by {client_ip}:{client_port}..." ) if (_database.search_password(login) != pass_hash): await _send_data( writer, 255, Extentions.defstr_to_bytes( "Password is incorrect.")) Logger.log( f"Deleting of '{login}' requested by {client_ip}:{client_port} was refused." ) continue _database.del_client(login) Logger.log( f"Deleting of '{login}' requested by {client_ip}:{client_port} was confirmed." ) await _send_data(writer, 4) timeout = 5 login = "" pass_hash = "" else: msg, _ = Extentions.bytes_to_str( Extentions.int_to_bytes(code) + data) Logger.log( f"Following message was resieved from {client_ip}:{client_port}:\n{msg}" ) except ConnectionResetError: Logger.log( f"Connection from {client_ip}:{client_port} closed by peer.") break except TimeoutError: Logger.log( f"Connection from {client_ip}:{client_port} closed by timeout." ) break writer.close()