def _connect_connection(connection, username, token, buffer_state, only_send=False, only_recv=False): """ Connect a connection to the server :param connection: a Connection object ot connect :param username: The username of the user :param token: The token to use to connect :param buffer_state: The buffer's state of the connection (See AdvancedSocket) :param only_send: Whether the connection only needs to send packets :param only_recv: Whether the connection only needs to recv packets :return connection status: A string with the connection status """ logging.debug("CONNECTIONS:Sending method: token") connection.socket.send( Message(MESSAGE_TYPES["server interaction"], "token")) logging.debug(f"CONNECTIONS:Sent method") logging.debug(f"CONNECTIONS:Sending user info:\n" f"{username}\n" f"{token}\n" f"{connection.type}\n" f"{connection.name}") connection.socket.send( Message( MESSAGE_TYPES["server interaction"], ( f"{username}\n" f"{token.decode()}\n" # TODO: you should not have to decode f"{connection.type}\n" f"{connection.name}"))) logging.debug(f"CONNECTIONS:Sent user's info") # Make sure the server is ready to start the main loop and # switch buffers states connection_status = connection.socket.recv().get_content_as_text() logging.debug(f"CONNECTIONS:{connection.name} " f"connection status: {connection_status}") # Make sure buffers are empty before switching connection.socket.send(Message(MESSAGE_TYPES["server interaction"], "ready"), block_until_buffer_empty=True) logging.debug(f"CONNECTIONS:{connection.name} sent ready") connection.socket.switch_state(*buffer_state) # TODO: what is this? you added the connection here before! connection.status = ConnectionStatus.CONNECTING if only_recv: connection.socket.close_send_thread() if only_send: connection.socket.close_recv_thread() connection.status = ConnectionStatus.CONNECTED return connection_status
def connector_close_connection(self, name, this_side): """ The method the connector runs when closing a connection :param name: The name of the connection to run :param this_side: whether this side of the network started the disconnect """ # TODO: can crash if connection does not exists connection = self.get_connection(name) connector = self.get_connection("connector") if this_side: connector.socket.send( Message(MESSAGE_TYPES["server interaction"], f"close:{connection.name}")) # if connection.status is ConnectionStatus.NOT_STARTED: # pass # TODO: Can this even happen? # elif connection.status not in (ConnectionStatus.NOT_STARTED, # ConnectionStatus.CONNECTING, # ConnectionStatus.CONNECTED): # pass # TODO: crash since connection is dead or error or closing if connection.status == ConnectionStatus.CONNECTED: connection.status = ConnectionStatus.DISCONNECTING logging.debug(f"CONNECTIONS:Connector set {name} to disconnecting") # TODO: what if connector closes or server closes? # while self.running and connector.status # is ConnectionStatus.CONNECTED: while True: time.sleep(0) # TODO: what if status is error? if connection.status is not ConnectionStatus.DISCONNECTING: break logging.debug(f"CONNECTIONS:{name} disconnected sending finished") connector.socket.send( Message(MESSAGE_TYPES["server interaction"], "finished")) # TODO: what if connector closes or server closes? # while self.running and connector.status # is ConnectionStatus.CONNECTED: while True: time.sleep(0) response = connector.socket.recv(block=False) if response is not None: logging.debug(("CLIENT:Closing connector response: " + response.get_content_as_text())) connection.status = ConnectionStatus.CLOSING logging.debug(f"CONNECTIONS:Connector set {name} to closing") break
def _update_screen_size(self, *_): width, height = self._app.screen_size logging.info(f"CONTROLLER:My screen size: {self._app.screen_size}") if self.session_settings.running: self.session_settings.settings_updates.put(Message( MESSAGE_TYPES["controller"], f"other screen size:{width}, {height}"))
def env_stop(): env_id = MSGProcessing.deserialization(request.data).env_id env = env_manager.env_dict[env_id] env.close() env_manager.delete_env(env_id) msg = Message(env_id=env_id, is_terminal=True) return MSGProcessing.serialization(msg)
def _update_frame(self, _): """ Update the image to the new frame """ try: # Try to receive a frame frame_message = self.connection.socket.recv(block=False) # If you did not receive a frame do not update the screen if frame_message is None: return logging.debug(f"FRAME:Received frame with " f"length: {len(frame_message.content)}") self.connection.socket.send( Message(MESSAGE_TYPES["controller"], "Message received")) frame_data = io.BytesIO(frame_message.content) frame_data.seek(0) logging.debug("FRAME:Creating core image") self.texture = CoreImage(frame_data, ext=self.image_format).texture logging.debug("FRAME:Reloading screen") self.reload() logging.debug("FRAME:SCREEN UPDATED") except Exception as e: # TODO: dont be broad print(e) self.stop() logging.error("FRAME:An error occurred", exc_info=True) return
def connector_close_all_connections(self, this_side): """ The method the connector runs when wanting to close all non connector connections and disconnect :param this_side: whether this side of the network started the disconnect """ # TODO: what about partner? # TODO: fix race condition here self.stop_adding_connections() connector = self.get_connection("connector") self._connector_close_non_connector(this_side) if this_side: connector.socket.send(Message(MESSAGE_TYPES["server interaction"], "disconnect:"), block_until_buffer_empty=True) # TODO: calling shutdown might prevent the socket from receiving # the disconnect request connector.disconnect() logging.info(f"client {self.user.username}'s connector is " f"disconnected") connector.status = ConnectionStatus.CLOSING logging.info(f"client {self.user.username}'s connector is " f"closing") try: connector.close() except Exception as e: print(e) logging.info((f"error while closing connector of " + str(self.user.username)), exc_info=True) else: logging.info(f"client {self.user.username}'s connector is closed")
def on_touch_down(self, touch): """ On touch down, move the mouse to that location and send it pos :param touch: The touch event object """ if (not self.is_tracking or self.click_button_spinner.collide_point(*touch.pos) or self.click_type_spinner.collide_point(*touch.pos)): return super().on_touch_down(touch) try: self.pos = touch.pos if touch.is_double_tap: action = "click" elif self.click_type == "move": action = "move" else: action = "press" x, y = self._transform_pos(touch.pos) self.connection.socket.send( Message(MESSAGE_TYPES["controller"], f"{action} {self.button_type} {x},{y}")) except Exception as e: print(e) self.is_tracking = False error_popup = ErrorPopup() error_popup.content_label.text = "Mouse crashed" error_popup.open() return super().on_touch_down(touch)
def on_touch_up(self, touch): """ on touch up, notify the server the mouse was released using the correct action :param touch: The touch event object """ if (not self.is_tracking or self.click_button_spinner.collide_point(*touch.pos) or self.click_type_spinner.collide_point(*touch.pos)): return False try: self.pos = touch.pos if self.click_type == "move": action = "move" else: action = "release" x, y = self._transform_pos(touch.pos) self.connection.socket.send( Message(MESSAGE_TYPES["controller"], f"{action} {self.button_type} {x},{y}")) except Exception as e: print(e) self.is_tracking = False error_popup = ErrorPopup() error_popup.content_label.text = "Mouse crashed" error_popup.open()
def reset_env(): msg = MSGProcessing.deserialization(request.data) assert msg.is_reset is True env_id = msg.env_id env = env_dict[env_id] initial_observation = env.reset() msg = Message(env_id=env_id, initial_observation=initial_observation) return MSGProcessing.serialization(msg)
def _send_frame(self): """ Send a frame to through the socket """ frame = self.screen_recorder.frame if frame is not None: self._connection.socket.send( Message(MESSAGE_TYPES["controlled"], frame)) self._can_send_frame = False
def _get_all_connected_usernames(self, connection): """ Send a user all connected users. :param connection: The connection to the user """ with self._clients_lock: usernames = [*self._clients.keys()] formatted_response = ", ".join(usernames) connection.socket.send( Message(MESSAGE_TYPES["server interaction"], formatted_response))
def __addAsMessage(self, messageBytes: bytes): if len( messageBytes ) == 0: # if the message is empty, add an empty message object - only the header self.messages.append( Message(self.sessionId, self.username, self.command, self.clientAddress, 0, self.messagesCount + 1, b'')) else: for i in range(0, math.ceil(len(messageBytes) / 256)): # Add a message for every 256 byte self.messages.append( Message( self.sessionId, self.username, self.command, self.clientAddress, 0, self.messagesCount + 1, messageBytes[i * 256:(i + 1) * 256 if (i + 1) * 256 <= len(messageBytes ) else len(messageBytes)])) self.messagesCount += 1
def update_screen_size(self, size): """ Update the size of the screen that the mouse is controlling :param size: The size of the screen """ width, height = size self._app.screen_size = size if self.session_settings.running: self.session_settings.settings_updates.put( Message(MESSAGE_TYPES["controlled"], f"other screen size:{width}, {height}"))
def _on_keyboard_key_down(self, _, keycode, _2, modifiers): if not self.is_tracking: return False self.connection.socket.send( Message(MESSAGE_TYPES["controller"], f"{keycode[1]}, press")) logging.debug(f"KEYBOARD:The key, {keycode}, has been pressed\n" f"modifiers are {modifiers!r}") # Return True to accept the key. Otherwise, it will be used by # the system. return True
def _get_all_usernames(self, connection, db_connection): """ Send all usernames to a user :param connection: The connection to the user :param db_connection: The connection to the database """ print(self.running) a = db_connection.get_all_usernames() logging.debug(f"MAIN SERVER:Sending all usernames: {a}") connection.socket.send( Message(MESSAGE_TYPES["server interaction"], ", ".join(a)))
def _on_keyboard_key_up(self, _, keycode): """ When a key is pressed, send its keycode to the server. :param keycode: The string representation of the key. """ if not self.is_tracking: return False self.connection.socket.send( Message(MESSAGE_TYPES["controller"], f"{keycode[1]}, release")) logging.debug(f"KEYBOARD:The key, {keycode}, has been released") return True
def env_step(): msg = MSGProcessing.deserialization(request.data) action = msg.action # print "action: {}".format(action) env_id = msg.env_id # print "env_id: {}".format(env_id) env = env_manager.env_dict[env_id] observation, reward, is_terminal, _ = env.step(action) msg = Message(observation=observation, reward=reward, is_terminal=is_terminal) return MSGProcessing.serialization(msg)
def create_env(): msg = MSGProcessing.deserialization(request.data) game_name = msg.game_name print "game_name: {}".format(game_name) env = gym.make(game_name) print "action_space: {}".format(list(range(0, env.action_space.n))) env_id = id_manager.create_id() print "env_id: {}".format(env_id) env_dict[env_id] = env msg = Message(env_id=env_id, action_space=list(range(0, env.action_space.n))) return MSGProcessing.serialization(msg)
def _set_partner(self, connection, client, partner_username): """ Set a client's partner. :param connection: The connection to the user :param client: The client :param partner_username: The username of the partner TODO: maybe return response code? Or response string? """ # TODO: close all connections to partner before switching with self._clients_lock: client.partner = self._clients[partner_username] connection.socket.send( Message(MESSAGE_TYPES["server interaction"], "set partner")) logging.info(f"set partner to: partner_username")
def _run_connection_to_partner(self, connection, client): """ Run a connection that sends data to the partner of the client and are buffered. :param connection: The connection that sends data. :param client: The client of the connection. :raise DisconnectError: (raises a subclass) if the client, partner or server disconnects :raise ValueError: if cant connect to the partner """ logging.info("starting main loop of connection to partner") buffer = MessageBuffer(False) partner_connection = self.get_partner_connection(connection, client) # TODO: maybe keep a reference to this thread to join it # when closing the connection partner_thread = threading.Thread( name=(f"Connection to partner {connection.name} of " f"User {client.user.username} to " f"{client.partner.user.username}"), target=self._send_messages_to_partner, args=(partner_connection, buffer)) partner_thread.start() try: while True: time.sleep(0) # Release GIL if partner_connection.status is ConnectionStatus.DISCONNECTING: raise PartnerConnectionDisconnectedError() elif connection.status is ConnectionStatus.DISCONNECTING: raise ConnectionDisconnectedError() elif not self.running: raise ServerDisconnectedError() # Try to receive a message. message = connection.socket.recv(block=False) if message is not None: # If you did receive a message, add it to the buffer. buffer.add(message) # Finally, send an ACK to get another message. connection.socket.send( Message(MESSAGE_TYPES["controlled"], "Message received")) except ConnectionDisconnectedError: partner_connection.status = ConnectionStatus.DISCONNECTING raise finally: partner_thread.join()
def _generate_token(self, name, connection, client): """ Create a token and send it to the client. :param name: The name of the connection to create the token for :param connection: The connector's connection :param client: the client of the connection """ logging.debug(f"CONNECTIONS:Making token for " f"{client.user.username}'s {name}") token = self._token_generator.generate(client.user.username, name) logging.debug(f"CONNECTIONS:Made token {token} " f"for {client.user.username}'s {name}") connection.socket.send( Message(MESSAGE_TYPES["server interaction"], "ok\n".encode(ENCODING) + token))
def _get_token(self, name): """ Request a token for a connection :param name: The name of the connection that need the token :return: The token as a bytes object """ connector = self.client.get_connection("connector") logging.debug(f"CONNECTIONS:Sending request for token for {name}") connector.socket.send( Message(MESSAGE_TYPES["server interaction"], f"generate token:{name}")) logging.debug(f"CONNECTIONS:Receiving token for {name}") response = connector.socket.recv().content.split("\n".encode(ENCODING)) logging.debug( f"CONNECTIONS:Received response for token for {name}: {response}") return {"status": response[0].decode(), "token": response[1]}
def _recv_message(self, buffer_size): """ Receive a message from a socket. :param buffer_size: The size of the buffer used by th recv :return: The packet as a message object :raise RuntimeError: If socket is closed from the other side. :raise ConnectionClosed: If connection was closed while sending """ length = int( self._recv_fixed_length_data( MESSAGE_LENGTH_LENGTH, DEFAULT_LENGTH_BUFFER_SIZE).decode(ENCODING)) message_type = self._recv_fixed_length_data( MESSAGE_TYPE_LENGTH, DEFAULT_TYPE_BUFFER_SIZE).decode(ENCODING) raw_content = self._recv_fixed_length_data(length, buffer_size) # lz4.frame.decompress(raw_content)) return Message(message_type, raw_content)
def addSignatureMessages(self, keyPass: str): if self.command == "HDS": return self.messagesCount += 2 # signature is 2 messages long self.__updateMessagesCount( ) # messages have to show the higher message count or signature validation fails self.messagesCount -= 2 # when adding the signature, the message number would be wrong allMessagesAsBytes: bytes = b'' for message in self.messages: allMessagesAsBytes += message.toBytes() h = SHA256.new(allMessagesAsBytes) if self.clientToServer: clientkfile = open('../client/client-keypair.pem', 'r') clientkeypairStr = clientkfile.read() clientkfile.close() key = RSA.import_key(clientkeypairStr, passphrase=keyPass) # Client private key else: serverkfile = open('../server/server-keypair.pem', 'r') serverkeypairStr = serverkfile.read() serverkfile.close() key = RSA.import_key(serverkeypairStr, passphrase=keyPass) # Server private key signer = PKCS1_PSS.new(key) signature = signer.sign(h) allMessagesCount = self.messagesCount + 2 for i in range(0, 2): self.messages.append( Message( self.sessionId, self.username, self.command, self.clientAddress, allMessagesCount, self.messagesCount + 1, signature[i * 256:(i + 1) * 256 if (i + 1) * 256 <= len(signature) else len(signature)])) self.messagesCount += 1
def create_env(): env = gym.make(MSGProcessing.deserialization(request.data).game_name) env_id = env_manager.add_env(env) msg = Message(env_id=env_id, action_space=list(range(0, env.action_space.n))) return MSGProcessing.serialization(msg)
frame = stream.getCurrentImage() # Image Processing drivingAngle, operation_flag, img_final = roadAnalyzer.getAngle(frame) # Display Images cv2.putText(frame, 'Driving Angle: {}'.format(-drivingAngle), (0, 600), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (100, 100, 255), 2, cv2.LINE_AA) cv2.imshow('Raw Image', frame) cv2.imshow('Proccessed Image', img_final) print('FLAG: ', operation_flag, ' Radiant: ', drivingAngle) # Send to NXT if SEND_ANGLE: if time.time() > start + SEND_PERIOD: msg = Message(flags=operation_flag, payload=drivingAngle) msg.send(com.s) start = time.time() if operation_flag == Message.HEADER_TURN_AROUND: time.sleep(2) roadAnalyzer = RoadAnalyzer() #receive flag and check if image processing needs to be resetted ''' Press Q on keyboard to exit''' if cv2.waitKey(25) & 0xFF == ord('q'): break # Closes all the frames cv2.destroyAllWindows()
def env_render(): env_id = MSGProcessing.deserialization(request.data).env_id env = env_manager.env_dict[env_id] env.render() msg = Message(env_id=env_id) return MSGProcessing.serialization(msg)
# -*- coding: utf-8 -*- from communication.message import Message from communication.message_processing import MSGProcessing if __name__ == '__main__': msg = Message('ns3', False, [0, 1], 0, [1, 1, 1, 1], None, 10, 1, False) result = MSGProcessing.send(msg) print result result = MSGProcessing.receive(result) print result print result.game_name print result.is_reset print result.action_space print result.action print result.initial_observation print result.observation print result.num_features print result.reward print result.is_terminal
def _connect_connection(self, connection_advanced_socket): """ Connect a connection :param connection_advanced_socket: The advanced socket of the connection. :return: Connection object and its client object and its connection to the database """ connecting_method = connection_advanced_socket.recv( ).get_content_as_text() logging.info("connecting method: " + connecting_method) # TODO: dont decode or use base64 on token connection_info = connection_advanced_socket.recv( ).get_content_as_text().split("\n") try: if connecting_method == "login": connection, client, db_connection = self._login( connection_advanced_socket, connection_info) elif connecting_method == "signup": connection, client, db_connection = self._signup( connection_advanced_socket, connection_info) elif connecting_method == "token": connection, client, db_connection = self._connect_with_token( connection_advanced_socket, connection_info) else: raise ValueError("Bad method") # If an value error occurs, set the connection status to the string of # the error except ValueError as e: error_string = e.args[0] if error_string in ("username does not exists", "password is wrong"): connection_status = "Username or password are wrong" else: connection_status = e.args[0] connection_advanced_socket.send(Message( MESSAGE_TYPES["server interaction"], connection_status), block_until_buffer_empty=True) raise else: try: connection_advanced_socket.send( Message(MESSAGE_TYPES["server interaction"], "ready")) # TODO: what if server closes? block=True can hang! # Make sure buffers are empty before switching client_connection_status = connection_advanced_socket.recv( block=True).get_content_as_text() if client_connection_status != "ready": logging.debug( f"CONNECTIONS:Crashed with " f"connection status: {client_connection_status}") raise ValueError( f"Client sent error:{client_connection_status}") logging.debug(f"CONNECTIONS:{connection.name} " f"connection status: {client_connection_status}") except Exception: connection.status = ConnectionStatus.ERROR client.remove_connection(connection.name) raise return connection, client, db_connection
def _add_connector(self, username, password, method, callback=None): """ Add a connection that connects other connection to the server :param username: The username of the user :param password: The password of the user :param method: Whether to log in or to sign up :param callback: The function to call after connecting (From the connecting thread) """ connector = self.client.get_connection("connector") connection_status = "Unexpected error (unreachable code)" try: socket = AdvancedSocket.create_connected_socket( self._server_address) connector.socket.start(socket, True, True) logging.debug(f"CONNECTION:Sending connector method: {method}") connector.socket.send( Message(MESSAGE_TYPES["server interaction"], method)) logging.debug(f"CONNECTIONS:Sent method") logging.debug(f"CONNECTIONS:Sending user info:\n" f"{username}\n" f"{password}\n" f"connector\n" f"connector") connector.socket.send( Message(MESSAGE_TYPES["server interaction"], (f"{username}\n" f"{password}\n" f"connector\n" f"connector"))) logging.debug("CONNECTIONS:Sent user's info") logging.debug("CONNECTIONS:Receiving connection status") connection_status = connector.socket.recv().get_content_as_text() if connection_status != "ready": raise ValueError(connection_status) logging.info(f"CONNECTIONS:Connection status of connector:" f" {connection_status}") connector.socket.send(Message(MESSAGE_TYPES["server interaction"], "ready"), block_until_buffer_empty=True) logging.debug(f"CONNECTIONS:connector sent ready") connector.status = ConnectionStatus.CONNECTED except ValueError as e: connector.status = ConnectionStatus.ERROR connection_status = str(e) # TODO: is that what you want? or should you call a func? connector.socket.shutdown() connector.socket.close() with self._client_lock: self._client = None raise except Exception as e: print(e) connector.status = ConnectionStatus.ERROR connection_status = "Exception while creating socket" # TODO: is that what you want? or should you call a func? connector.socket.shutdown() connector.socket.close() with self._client_lock: self._client = None raise finally: if callback is not None: callback(connection_status)