def _client_handler(self, c, ca, uid): """ Handle authenticated client for connections with other clients :param c: client socket object :param ca: client IP address """ while True: send_json_message( c, { 'Response': 'Success', 'Message': 'Send UID with whom youd like to communicate' }) # Receive UID with whom to communicate uid_msg = receive_json_message(c) if uid_msg is None: print(f'{uid}:{ca} has disconnected') self._connections.remove((c, ca, uid)) break print( f'\nClient {uid}:{ca} wishes to communicate with {uid_msg["UID"]}' ) # Establish P2P connection if self._establish_p2p(c, ca, uid, uid_msg['UID']): break
def start(self): """ Run the P2P client, connect to the server and send messages """ # Connect to the server self.p2p_c.connect((self.peer_ip, self.peer_port)) print(f'Established P2P connection with ({self.peer_ip},{self.peer_port})') print(f'\nPress enter to join P2P chat with {self.peer_uid}') # Start thread for message sending send_thread = threading.Thread(target=self._send_message) send_thread.daemon = True send_thread.start() # Listen for incoming messages from the server while True: msg = receive_json_message(self.p2p_c) if msg is None: print(f'Lost connection to the peer {self.peer_uid}:({self.peer_ip},{self.peer_port}), closing...') break aes_key = generate_symmetric_key(self.private_key, self.peer_ik) decrypted_msg = decrypt_message(aes_key, bytes.fromhex(msg['iv']), bytes.fromhex(msg['Message'])) print(f'{self.peer_uid} ({self.peer_ip},{self.peer_port}): {decrypted_msg.decode()}')
def _listen(self, send_thread): """ Listen for server messages """ peer_msg = None while True: peer_msg = receive_json_message(self._client_socket) check_connection_client(peer_msg) # Incoming P2P connection if peer_msg['Response'] == 'P2P' and 'Message' in peer_msg: print(f'\nServer: {peer_msg["Message"]}') elif peer_msg['Response'] == 'P2P': print( f'\nServer: Initiate P2P with UID: {peer_msg["PeerUID"]}, IP: {peer_msg["PeerIP"]}, IK: {bytes_to_key(bytes.fromhex(peer_msg["PeerIK"]))}' ) send_thread.stop() self._client_socket.close() print( f'Close connection to the server, so that we can perform P2P' ) break return peer_msg
def _verify_with_server(self): """ Send UID and public key to the server to verify """ # Send message to the server time.sleep(1) send_json_message(self._client_socket, { 'UID': self._uid, 'IK': key_to_bytes(self._ik).hex() }) # Receive response response_msg = receive_json_message(self._client_socket) check_connection_client(response_msg) print( f'Server ({response_msg["Response"]}): {response_msg["Message"]}') if response_msg['Response'] == 'Failure': print('Quitting...') sys.exit(0)
def _client_gateway(self, c, ca): """ Gateway for a new client connection :param c: client socket object :param ca: client IP address """ print(f'Client {ca} goes through gateway') # Identity confirmation verification_msg = receive_json_message(c) if verification_msg is None: print(f'{ca} has disconected') return res = self._verify_user(verification_msg) # Give response to the client if not res: send_json_message( c, { 'Response': 'Failure', 'Message': 'Could not authenticate with the server' }) print(f'Ending connection with client {ca}') c.close() self._print_connections() return print(f'Client {ca} has successfully authenticated with the server') # Add to connections list found = False for i, conn in enumerate(self._connections): if conn[2] == verification_msg['UID']: self._connections[i] = (c, ca, verification_msg['UID']) found = True break if not found: self._connections.append((c, ca, verification_msg['UID'])) self._print_connections() # Handle the client self._client_handler(c, ca, verification_msg['UID'])
def start(self): """ Run P2P server, listen for connections and communicate with the client """ # Wait for expected connection while True: p2p_c, p2p_ca = self.p2p_s.accept() if not p2p_ca[0] == self.peer_ip[0]: print(f'Unknown connection from {p2p_ca}, close') p2p_c.close() continue self.p2p_c = p2p_c self.p2p_ca = p2p_ca break print(f'Established P2P connection with {self.p2p_ca}') print(f'\nPress enter to join P2P chat with {self.peer_uid}') # Start thread for message sending send_thread = threading.Thread(target=self._send_message) send_thread.daemon = True send_thread.start() # Listen for incoming messages from the client while True: msg = receive_json_message(self.p2p_c) if msg is None: print( f'Lost connection to the peer {self.peer_uid}:({self.peer_ip}), closing...' ) break aes_key = generate_symmetric_key(self.private_key, self.peer_ik) decrypted_msg = decrypt_message(aes_key, bytes.fromhex(msg['iv']), bytes.fromhex(msg['Message'])) print(f'{self.peer_uid} ({self.p2p_ca}): {decrypted_msg.decode()}')