def signal_handler(sig, frame): """Wraps all exit handling related to networked classes/threads """ print("Caught ctrl+c: ") global program_ended program_ended = True Handshake.set_got_reponse() Server.set_got_msg() AppManager.kill_app()
def start_server(ip_address): """ Start the server and wait for a connection :param ip_address: ip address of the client :return .Server object """ server = Server() # This method ends when a connection is made server.start_server() return server
def start_replication(self): """Starts replication.""" # HACK ALERT! # if self.__find_local_server(): # Found a local server running -> connect to it self.__client = Client(("localhost", 54879)) self.__client.connect("Player2") else: # No local server running -> run one self.__server = Server() self.__server.start()
def setUpClass(self): try: self.client = Client(constants.MODE_CLIENT, ('127.0.0.1', constants.DEFAULT_PORT)) self.server = Server() self.server.start(constants.DEFAULT_PORT) # Run the test server thread self.testsServerThread = TestsServerThread(self.server) self.testsServerThread.start() except Exception as e: print "Failed to start server: " + str(e) raise e
def __startServer(self): try: self.server = Server() self.server.start(int(self.port)) except exceptions.NetworkError as ne: QMessageBox.critical(self.chatWindow, errors.FAILED_TO_START_SERVER, errors.FAILED_TO_START_SERVER + ": " + str(ne)) self.__restart()
def setUp(self): self.server = Server({'DEBUG': True}) port = randint(5600, 6600) self.server_thread = Thread(target=self.server.run, args=(port, )) self.server_thread.start() self.wait_server() self.client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_sock.settimeout(2) self.client_sock.connect(('127.0.0.1', port))
def __init__(self, interactive_port, broadcast_port, logger, encryption_scheme, data_root="data/"): """ Start a Composte Server listening on interactive_port and broadcasting on broadcast_port. Logs are directed to logger, messages are transparently encrypted with encryption_scheme.encrypt() and encryption_scheme.decrypt(), and data is stored in the directory data_root. """ self.__server = NetworkServer(interactive_port, broadcast_port, logger, encryption_scheme) self.__server.start_background(self.__handle, self.__preprocess, self.__postprocess) self.__users = None self.__projects = None self.__contributors = None self.version = misc.get_version() self.__server.info("Composte server version {}".format(self.version)) self.__data_root = data_root self.__project_root = os.path.join(self.__data_root, "users") self.__dlock = Lock() self.__done = False self.__pool = bookkeeping.ProjectPool() # A better solution would have a lock for every project, but in a # classroom demo this won't be an issue self.__flushing = Lock() def is_done(self): with self.__dlock: return not self.__done self.__timer = timer.every(300, 2, lambda: self.__pool.map(self.flush_project), lambda: is_done(self)) try: os.makedirs(self.__project_root) except FileExistsError as e: pass self.sessions = {}
settings_group.add_argument('-P', '--port', type=int, dest='port', help='Port for the server to bind to.') settings_group.add_argument('-t', '--default-tag', dest='default_tag', help='Tag to default to when a task is created without a tag.') settings_group.add_argument('-n', '--hostname', dest='hostname', help='MySQL hostname to use. Defaults to "todo".') settings_group.add_argument('-u', '--username', dest='username', help='MySQL username to use. Defaults to "todo".') settings_group.add_argument('-p', '--password', dest='password', help='MySQL password to use. Defaults to "todo".') settings_group.add_argument('-d', '--database', dest='database', help='MySQL database to use. Defaults to "todo".') args = vars(parser.parse_args()) config_structure = {'Todo' : ['port', 'default_tag'], 'MySQL' : ['hostname', 'username', 'password', 'database']} config = todo_config.get_config(args, config_structure) # Start the Server with the port or the default server = Server() if 'port' in config: server.start(config['port']) del config['port'] else: server.start(Server.DEFAULT_PORT) # Accept incoming connections and run them in separate threads while True: connection = ServerThread(server.accept(), config) connection.start()
import pygame from copy import deepcopy from classes.bishop import Bishop from classes.king import King from classes.knight import Knight from classes.pawn import Pawn from classes.queen import Queen from classes.rook import Rook from network.server import Server from brain.board import Board from brain.game import Game host = "192.168.1.19" port = 50000 if __name__ == "__main__": server = Server(host, port, 2) server.connexion_of_client() board = Board() game = Game(board, server) game.launchGame() server.mySocket.close()
class ReplicationManager(GameObjectBase): """ Manages GameObjects that are marked for replication. """ def __init__(self): super().__init__() self.__replicators = {} self.__client = None self.__server = None def add_object(self, replication_id, gob): """Adds a GameObject to be replicated from server to connected clients.""" self.__replicators[replication_id] = gob def __compile_replication_data(self): """ Compiles and returns the dictionary with the data for all the register replicators. The server calls this function after all the game objects have been updated. The compiled data is sent by the server to all the connected clients. """ replication_data = {} for rep_id, gob in self.__replicators.items(): replication_data[rep_id] = {} for rep_prop in gob.get_replicated_props(): replication_data[rep_id][rep_prop.name] = rep_prop.packer.pack( getattr(gob, rep_prop.getter)) return replication_data def __apply_replication_data(self, game_state): """ Applies the data received by the client to the registered game objects. The client calls this function at the end of each game update to ensure that all the replicated game objects are in sync with their primary replicas existing on the server. """ for replication_id, replication_data in game_state.items(): gob = self.__replicators.get(replication_id) if gob: for rep_prop in gob.get_replicated_props(): new_value = replication_data.get(rep_prop.name) if new_value: setattr(gob, rep_prop.setter, rep_prop.packer.unpack(new_value)) def start_replication(self): """Starts replication.""" # HACK ALERT! # if self.__find_local_server(): # Found a local server running -> connect to it self.__client = Client(("localhost", 54879)) self.__client.connect("Player2") logging.debug("Started client") else: # No local server running -> run one self.__server = Server() self.__server.start() logging.debug("Started server") # HACK ALERT! # def update(self, delta): """Updates the replication manager.""" if self.__client: if self.__client.tick(): if self.__client.state == ClientState.PLAYING: self.__apply_replication_data( self.__client.get_game_state()) self.__client.reset_game_state() else: self.__client = None elif self.__server: self.__server.propagate_game_state( self.__compile_replication_data()) self.__server.tick() def propagate_input(self, inputs): """Sets the list of input actions collected by the game in the current frame. These are sent to the server.""" if self.__client: self.__client.set_inputs(inputs) @classmethod def __find_local_server(cls): """Tries to connect to a local server. Returns True if successful, False otherwise.""" client = Client(("localhost", 54879)) client.connect("Player2") found_server = False try: client.tick() found_server = True except BrokenPipeError: pass finally: client.stop() return found_server
class NcursesUI(object): def __init__(self, mode, port, host): self.mode = mode self.port = port self.host = host def start(self): curses.wrapper(self.run) def stop(self): # If a client is connected, try to end the connection gracefully if hasattr(self, 'client'): self.client.disconnect() if hasattr(self, 'server'): self.server.stop() def run(self, screen): self.screen = screen (self.height, self.width) = self.screen.getmaxyx() # Change the colors, clear the screen and set the overall border self.setColors() self.screen.clear() self.screen.border(0) # Create the status and chat input windows self.makeChatWindow() self.makeStatusWindow() self.makeChatInputWindow() self.screen.refresh() # Try to load a keypair if one was saved or generate a new keypair self.loadOrGenerateKepair() # Show the options menu self.showOptionsMenuWindow(showStartOption=True) # Get the server/client mode if not given if self.mode == None: self.showOptionsWindow() if self.mode == constants.MODE_SERVER: self.startServer() self.waitForClient() elif self.mode == constants.MODE_CLIENT: # Get the host if not given if self.host == None: self.getHost() self.connectToServer() self.handleNewConnection() def waitForClient(self): while True: # Show the waiting for connections dialog dialogWindow = CursesDialog(self.screen, "Waiting for connection...") dialogWindow.show() self.client = self.server.accept(self.crypto) dialogWindow.hide() # Show the accept dialog if self.showAcceptWindow() == ACCEPT: break else: self.client.disconnect() # Do the handshake with the client try: self.client.doHandshake() except exceptions.NetworkError as ne: CursesDialog(self.screen, str(ne), errors.TITLE_NETWORK_ERROR, isError=True).show() self.client.disconnect() except exceptions.CryptoError as ce: CursesDialog(self.screen, str(ce), errors.TITLE_CRYPTO_ERROR, isError=True).show() self.client.disconnect() def connectToServer(self): try: dialogWindow = CursesDialog(self.screen, "Connecting to server...", "", False) dialogWindow.show() self.client = Client(constants.MODE_CLIENT, (self.host, self.port), crypto=self.crypto) self.client.connect() except exceptions.GenericError as ge: CursesDialog(self.screen, str(ge), errors.FAILED_TO_CONNECT, isError=True).show() # Do the handshake with the server try: self.client.doHandshake() dialogWindow.hide() except exceptions.NetworkError as ne: self.client.disconnect() dialogWindow.hide() CursesDialog(self.screen, str(ne), errors.TITLE_NETWORK_ERROR, isError=True).show() except exceptions.CryptoError as ce: self.client.disconnect() dialogWindow.hide() CursesDialog(self.screen, str(ce), errors.TITLE_CRYPTO_ERROR, isError=True).show() def handleNewConnection(self): # Set the hostname of who we're connected to in the status window self.setStatusWindow() # Add a hint on how to display the options menu self.screen.addstr(0, 5, "Ctrl+U for options") self.screen.refresh() # Start the sending and receiving threads self.startThreads() # Keep the main thread alive so the daemon threads don't die while True: time.sleep(10) def startThreads(self): ncursesThreads.CursesSendThread(self).start() ncursesThreads.CursesRecvThread(self).start() def setColors(self): if curses.has_colors(): curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_GREEN) self.screen.bkgd(curses.color_pair(1)) def showOptionsWindow(self): optionsWindow = self.screen.subwin(6, 11, self.height/2 - 3, self.width/2 - 6) optionsWindow.border(0) # Enable arrow key detection for this window optionsWindow.keypad(True) # Disable the cursor curses.curs_set(0) optionsWindow.addstr(1, 1, "Run as:") pos = constants.MODE_SERVER while True: if pos == constants.MODE_SERVER: optionsWindow.addstr(3, 2, "Server", curses.color_pair(4)) optionsWindow.addstr(4, 2, "Client") else: optionsWindow.addstr(3, 2, "Server") optionsWindow.addstr(4, 2, "Client", curses.color_pair(4)) self.screen.refresh() key = optionsWindow.getch() # Enter key if key == ord('\n'): break elif pos == constants.MODE_SERVER: pos = constants.MODE_CLIENT elif pos == constants.MODE_CLIENT: pos = constants.MODE_SERVER # Re-enable the cursor curses.curs_set(2) # Get rid of the options window optionsWindow.clear() optionsWindow.refresh() self.mode = pos def showAcceptWindow(self): dialogWidth = 23 + len(self.client.getHostname()); acceptWindow = self.screen.subwin(6, dialogWidth, self.height/2 - 3, self.width/2 - int(dialogWidth/2)) acceptWindow.border(0) # Enable arrow key detection for this window acceptWindow.keypad(True) # Disable the cursor curses.curs_set(0) acceptWindow.addstr(1, 1, "Got connection from %s" % self.client.getHostname()) pos = ACCEPT while True: if pos == ACCEPT: acceptWindow.addstr(3, 2, "Accept", curses.color_pair(4)) acceptWindow.addstr(4, 2, "Reject") else: acceptWindow.addstr(3, 2, "Accept") acceptWindow.addstr(4, 2, "Reject", curses.color_pair(4)) self.screen.refresh() key = acceptWindow.getch() # Enter key if key == ord('\n'): break elif pos == ACCEPT: pos = REJECT elif pos == REJECT: pos = ACCEPT # Re-enable the cursor curses.curs_set(2) # Get rid of the accept window acceptWindow.clear() acceptWindow.refresh() return pos def makeChatWindow(self): self.chatWindow = self.screen.subwin(self.height-4, self.width-2, 1, 1) self.chatWindow.scrollok(True) def makeStatusWindow(self): self.statusWindow = self.screen.subwin(self.height-3, self.width-23) self.statusWindow.border(0) self.statusWindow.addstr(1, 1, "Disconnected") def makeChatInputWindow(self): self.textboxWindow = self.screen.subwin(1, self.width-25, self.height-2, 1) self.textbox = curses.textpad.Textbox(self.textboxWindow, insert_mode=True) curses.textpad.rectangle(self.screen, self.height-3, 0, self.height-1, self.width-24) self.textboxWindow.move(0, 0) def getHost(self): self.hostWindow = self.screen.subwin(3, 26, self.height/2 - 1, self.width/2 - 13) self.hostWindow.border(0) self.hostWindow.addstr(1, 1, "Host: ") self.hostWindow.refresh() # Turn on echo and wait for enter key to read buffer curses.echo() curses.nocbreak() self.host = self.hostWindow.getstr(1, 7) # Turn off echo and disable buffering curses.cbreak() curses.noecho() # Get rid of the host window self.hostWindow.clear() self.screen.refresh() def setStatusWindow(self): self.statusWindow.clear() self.statusWindow.border(0) self.statusWindow.addstr(1, 1, self.client.getHostname()) self.statusWindow.refresh() def startServer(self): try: self.server = Server() self.server.start(int(self.port)) except exceptions.NetworkError as ne: CursesDialog(screen, errors.FAILED_TO_START_SERVER, str(ne), isError=True).show() def showOptionsMenuWindow(self, showStartOption=False): menuWindow = self.screen.subwin((9 if showStartOption else 8), 40, 3, self.width/2 - 20) menuWindow.border(0) # Enable arrow key detection for this window menuWindow.keypad(True) pos = 1 while True: # Disable the cursor curses.curs_set(0) while True: menuItem = 1 if showStartOption: menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Start chat", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Show public key fingerprints", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Save current keypair", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Clear saved keypair", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Show help", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Close menu", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuItem += 1 menuWindow.addstr(menuItem, 1, str(menuItem) + ".| Quit application", curses.color_pair(4) if pos == menuItem else curses.color_pair(1)) menuWindow.refresh() key = menuWindow.getch() if key == curses.KEY_DOWN and pos < (7 if showStartOption else 6): pos += 1 elif key == curses.KEY_UP and pos > 1: pos -= 1 # Wrap around from top of menu elif key == curses.KEY_UP and pos == 1: pos = (7 if showStartOption else 6) # Wrap around from bottom of menu elif key == curses.KEY_DOWN and pos == (7 if showStartOption else 6): pos = 1 # Enter key elif key == ord('\n'): break # Move the selected item by 1 to adjust for the lack of a start option if not showStartOption: pos += 1 # Process the selected option if pos == 1: break if pos == 2: try: CursesFingerprintDialog(self.screen, self.crypto.getLocalFingerprint(), self.crypto.getRemoteFingerprint()).show() except exceptions.CryptoError: CursesDialog(self.screen, "Public key(s) not generated/received yet.", isBlocking=True).show() elif pos == 3: passphrase = self.getKeypairPassphrase(True) utils.saveKeypair(self.crypto, passphrase) CursesDialog(self.screen, "This keypair will be used for all subsequent chats", "Keypair Saved", isBlocking=True).show() elif pos == 4: utils.clearKeypair() CursesDialog(self.screen, "Keypair cleared", isBlocking=True).show() elif pos == 5: CursesDialog(self.screen, "Read the docs at https://cryptully.readthedocs.org/en/latest/", isBlocking=True).show() elif pos == 6: break elif pos == 7: os.kill(os.getpid(), signal.SIGINT) # Shift the selected item position back if not showStartOption: pos -= 1 # Re-enable the cursor curses.curs_set(2) # Get rid of the accept window menuWindow.clear() menuWindow.refresh() def getKeypairPassphrase(self, verify=False): passphraseWindow = self.screen.subwin(3, 36, self.height/2 - 1, self.width/2 - 18) # Turn on echo and wait for enter key to read buffer curses.echo() curses.nocbreak() while True: passphraseWindow.border(0) passphraseWindow.addstr(1, 1, "Passphrase: ") passphraseWindow.refresh() passphrase = getpass('') if not verify: break passphraseWindow.clear() passphraseWindow.border(0) passphraseWindow.addstr(1, 1, "Verify: ") passphraseWindow.refresh() verifyPassphrase = getpass('') if passphrase == verifyPassphrase: break else: curses.cbreak() CursesDialog(self.screen, errors.VERIFY_PASSPHRASE_FAILED, '', isBlocking=True).show() curses.nocbreak() # Turn off echo and disable buffering curses.cbreak() curses.noecho() # Get rid of the passphrase window passphraseWindow.clear() passphraseWindow.refresh() return passphrase def loadOrGenerateKepair(self): self.crypto = Crypto() if utils.doesSavedKeypairExist(): while(True): passphrase = self.getKeypairPassphrase() try: utils.loadKeypair(self.crypto, passphrase) break except exceptions.CryptoError: CursesDialog(self.screen, errors.BAD_PASSPHRASE, '', isBlocking=True).show() # We still need to generate an AES key self.crypto.generateAESKey() else: self.crypto.generateKeys()
import sys from network.server import Server server = Server() server.run()
class ReplicationManager(GameObjectBase): """ Manages GameObjects that are marked for replication. """ def __init__(self): super().__init__() self.__replicators = {} self.__client = None self.__server = None def add_object(self, replication_id, gob): """Adds a GameObject to be replicated from server to connected clients.""" self.__replicators[replication_id] = gob # DEBUG # logging.debug(f"Added {gob}") logging.debug(self.__replicators) for rep_id, gob in self.__replicators.items(): logging.debug(rep_id) for prop in gob.get_replicated_props(): logging.debug(prop) # DEBUG # def __get_replication_data(self): """ Compiles and returns the dictionary with the data for all the register replicators. The server calls this function after all the game objects have been updated. The compiled data is sent by the server to all the connected clients. """ replication_data = {} for rep_id, gob in self.__replicators.items(): replication_data[rep_id] = {} for prop in gob.get_replicated_props(): replication_data[rep_id][prop] = getattr(gob, prop) return replication_data def __apply_replication_data(self): """ Applies the data received by the client to the registered game objects. The client calls this function at the end of each game update to ensure that all the replicated game objects are in sync with their primary replicas existing on the server. """ pass def start_replication(self): """Starts replication.""" # HACK ALERT! # if self.__find_local_server(): # Found a local server running -> connect to it self.__client = Client(("localhost", 54879)) self.__client.connect("Player2") else: # No local server running -> run one self.__server = Server() self.__server.start() # HACK ALERT! # def update(self, delta): if self.__client: self.__client.tick() @classmethod def __find_local_server(cls): """Tries to connect to a local server. Returns True if successful, False otherwise.""" client = Client(("localhost", 54879)) client.connect("Player2") found_server = False try: client.tick() found_server = True except BrokenPipeError: pass finally: client.stop() return found_server
def startServer(self): try: self.server = Server() self.server.start(int(self.port)) except exceptions.NetworkError as ne: CursesDialog(screen, errors.FAILED_TO_START_SERVER, str(ne), isError=True).show()
def main(log, readlog, only_odometry, sensorFile, odomFile, resultname, mapconfig): initialized = False sensor = None navigation = None robot = None server = None try: #Initialize Sensor if (readlog): sensor = FileXTION(sensorFile) else: sensor = XTION(log) #Initialize Slam if (only_odometry): slam = Deterministic_SLAM(sensor, mapconfig.SIZE_PIXELS, mapconfig.SIZE_METERS) else: slam = My_SLAM(sensor, mapconfig.SIZE_PIXELS, mapconfig.SIZE_METERS, random_seed=SEED) #Initialize Robot if (readlog): robot = FileDrone(odomFile) else: robot = NetworkVehicle(log) robot.initialize() #Open Controll and Map Server server = Server(slam, mapconfig.SIZE_PIXELS, robot) server.start() #Initialize Navigation if (not readlog): navigation = Navigation(slam, mapconfig, robot.getSize(), RELEVANT_LIDARS, SECURITY_DIST_MM, Commands) navigation.start() #Monitors scanno = 0 dist = 0 timePast = 0 trajectory = [] start_sec = time() #Make initial scan scan = sensor.scan() initialized = True #Main loop while (True): scanno += 1 #get command if (readlog): command = None else: command = navigation.update(scan) if (command == None): print "Navigation terminated." break #send command and get odometry velocities = robot.move(command) #check if velocities are valid if (velocities == None): print "Robot terminated." break #update monitors dist += velocities[0] timePast += velocities[2] #get scan scan = sensor.scan() #check if scan is valid if (len(scan) <= 0): print "Sensor terminated." break #Update SLAM slam.update(scan, velocities) # Get new position x_mm, y_mm, theta_degrees = slam.getpos() # Add new position to trajectory trajectory.append((x_mm, y_mm)) except KeyboardInterrupt: print "Program stoped!" finally: print "Shutting down." if (sensor != None): sensor.shutdown() if (navigation != None): navigation.stop() if (robot != None): robot.shutdown() if (server != None): server.close() if (initialized): #Print results elapsed_sec = time() - start_sec print('\n%d scans in %f sec = %f scans / sec' % (scanno, elapsed_sec, scanno / elapsed_sec)) print('Distance traveled:%f mm in %fs' % (dist, timePast)) #generate map mapbytes = createMap(slam, trajectory, mapconfig) # Save map and trajectory as png file mapconfig.safeaspng(mapbytes, resultname)
""" print("Caught ctrl+c: ") global program_ended program_ended = True Handshake.set_got_reponse() Server.set_got_msg() AppManager.kill_app() if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) parser = Parser() args = parser.args # Set values obtained from parser (where applicable) Server.set_run_port(args.server_run_port) server = None # Will store data, addr after recvfrom client_data = Queue() handshake = Handshake(args, args.silent) handshake.perform_handshake() # Startup the server server = Server(client_data, args.silent) server.start() # Takes a long time so do this ASAP app = AppManager(args.debug_app, args.web_app_port, args.silent, server,
class QtUI(QApplication): def __init__(self, argv, mode, port, host): QApplication.__init__(self, argv) self.mode = mode self.port = port self.host = host self.isEventLoopRunning = False self.connectedToClient = False self.isLightTheme = qtUtils.isLightTheme(self.palette().color(QPalette.Window)) self.aboutToQuit.connect(self.stop) def start(self): self.timer = QTimer() self.timer.start(500) self.timer.timeout.connect(lambda: None) # Show mode dialog if a mode wasn't given if self.mode is None: self.mode = QModeDialog.getMode(self.isLightTheme) # If the user closed the mode dialog by not selected a mode, stop the app if self.mode is None: qtUtils.exitApp() # Show the chat window self.chatWindow = QChatWindow(None, None, self.isLightTheme) self.chatWindow.show() self.__loadOrGenerateKepair() if self.mode == constants.MODE_SERVER: self.__startServer() self.__waitForClient() elif self.mode == constants.MODE_CLIENT: # Get the host if not given if self.host is None: self.host, ok = QInputDialog.getText(self.chatWindow, "Hostname", "Host:") if not ok: self.__restart() return self.__connectToServer() if not self.isEventLoopRunning: self.isEventLoopRunning = True self.exec_() def stop(self): self.__endConnections() self.quit() def __restart(self): self.__endConnections() self.__restartHelper() self.start() def __endConnections(self): if hasattr(self, 'acceptThread'): self.acceptThread.quit() elif hasattr(self, 'connectThread'): self.connectThread.quit() if hasattr(self, 'sendThread'): self.sendThread.quit() if hasattr(self, 'recvThread'): self.recvThread.quit() # If a client is connected, try to end the connection gracefully if hasattr(self, 'client'): self.client.disconnect() if hasattr(self, 'server'): self.server.stop() def __restartHelper(self): self.mode = None self.host = None self.closeAllWindows() if hasattr(self, 'waitingDialog'): del self.waitingDialog if hasattr(self, 'chatWindow'): del self.chatWindow def __loadOrGenerateKepair(self): self.crypto = Crypto() if utils.doesSavedKeypairExist(): while(True): passphrase = qtUtils.getKeypairPassphrase(self.isLightTheme) # Restart the application if the user did not provide a passphrase if passphrase is None: self.__restart() return try: utils.loadKeypair(self.crypto, passphrase) break except exceptions.CryptoError: QMessageBox.warning(self.chatWindow, errors.BAD_PASSPHRASE, errors.BAD_PASSPHRASE_VERBOSE) # We still need to generate an AES key self.crypto.generateAESKey() else: self.crypto.generateKeys() def __startServer(self): try: self.server = Server() self.server.start(int(self.port)) except exceptions.NetworkError as ne: QMessageBox.critical(self.chatWindow, errors.FAILED_TO_START_SERVER, errors.FAILED_TO_START_SERVER + ": " + str(ne)) self.__restart() def __waitForClient(self): # Start the accept thread self.acceptThread = qtThreads.QtServerAcceptThread(self.server, self.crypto, self.__postAccept) self.acceptThread.start() # Show the waiting dialog self.waitingDialog = QWaitingDialog(self.chatWindow, "Waiting for connection...", self.isLightTheme, self.__userClosedWaitingDialog, showIP=True) self.waitingDialog.show() def __connectToServer(self): # Create the client object to use for the connection self.client = Client(constants.MODE_CLIENT, (self.host, self.port), crypto=self.crypto) # Start the connect thread self.connectThread = qtThreads.QtServerConnectThread(self.client, self.__postConnect, self.__connectFailure) self.connectThread.start() # Show the waiting dialog self.waitingDialog = QWaitingDialog(self.chatWindow, "Connecting to server...", self.isLightTheme, self.__userClosedWaitingDialog) self.waitingDialog.show() @pyqtSlot(Client) def __postAccept(self, client): self.connectedToClient = True self.client = client self.waitingDialog.close() # Show the accept dialog accept = QAcceptDialog.getAnswer(self.chatWindow, self.client.getHostname()) # If not accepted, disconnect and wait for a client again if not accept: self.client.disconnect() self.__waitForClient() return # Do the handshake with the client try: client.doHandshake() except exceptions.NetworkError as ne: self.client.disconnect() self.__waitForClient() self.__startChat() @pyqtSlot() def __postConnect(self): self.connectedToClient = True self.waitingDialog.close() self.__startChat() @pyqtSlot(str) def __connectFailure(self, errorMessage): QMessageBox.critical(self.chatWindow, errors.FAILED_TO_CONNECT, errorMessage) self.__restart() @pyqtSlot() def __userClosedWaitingDialog(self): self.waitingDialog.hide() # If the waiting dialog was closed before we connected to the client, # it means that the user closed the dialog and we should restart the app if not self.connectedToClient: self.__restart() def __startChat(self): # Start the sending and receiving thread self.recvThread = qtThreads.QtRecvThread(self.client, self.chatWindow.appendMessage, self.__threadError) self.recvThread.start() self.sendThread = qtThreads.QtSendThread(self.client, self.__threadError) self.sendThread.start() self.chatWindow.client = self.client self.chatWindow.messageQueue = self.sendThread.messageQueue self.chatWindow.showNowChattingMessage() @pyqtSlot(str, str) def __threadError(self, title, message): QMessageBox.critical(self.chatWindow, title, message) self.__restart()
if __name__ == "__main__": net_conf_ui = NetworkConfigurationUi() info = net_conf_ui.run() if not any(info): sys.exit() is_hosting_server, ip, port = info receive_queue = Queue() server = None client = None if is_hosting_server: player = Players.P1 server = Server('127.0.0.1', 65432) server.run() client = Client('127.0.0.1', 65432, receive_queue) time.sleep(1) if client.connect() is not True: sys.exit() client.listen() wait_dialog = ServerWaitingDialog('127.0.0.1', 65432, server.get_number_of_players) wait_dialog.run() else: player = Players.P2 client = Client(ip, port, receive_queue)
class ComposteServer: __project_extension = ".heap" __metadata_extension = ".meta" # I'm so sorry __register_lock = Lock() def __init__(self, interactive_port, broadcast_port, logger, encryption_scheme, data_root="data/"): """ Start a Composte Server listening on interactive_port and broadcasting on broadcast_port. Logs are directed to logger, messages are transparently encrypted with encryption_scheme.encrypt() and encryption_scheme.decrypt(), and data is stored in the directory data_root. """ self.__server = NetworkServer(interactive_port, broadcast_port, logger, encryption_scheme) self.__server.start_background(self.__handle, self.__preprocess, self.__postprocess) self.__users = None self.__projects = None self.__contributors = None self.version = misc.get_version() self.__server.info("Composte server version {}".format(self.version)) self.__data_root = data_root self.__project_root = os.path.join(self.__data_root, "users") self.__dlock = Lock() self.__done = False self.__pool = bookkeeping.ProjectPool() # A better solution would have a lock for every project, but in a # classroom demo this won't be an issue self.__flushing = Lock() def is_done(self): with self.__dlock: return not self.__done self.__timer = timer.every(300, 2, lambda: self.__pool.map(self.flush_project), lambda: is_done(self)) try: os.makedirs(self.__project_root) except FileExistsError as e: pass self.sessions = {} def flush_project(self, project, count): """ Flush project to backing storage """ with self.__flushing: self.write_project(project) # Database interactions def register(self, uname, pword, email): """ Register a new user. Username must be unique per user database. """ hash_ = auth.hash(pword) with ComposteServer.__register_lock: hopefully_None = self.__users.get(uname) if hopefully_None.uname is not None: return ("fail", "Username is taken") # Apparently exceptions on writes cause the database to lock... try: self.__users.put(uname, hash_, email) except sqlite3.IntegrityError: return ("fail", "Username is taken") except sqlite3.DatabaseError as e: # raise e return ("fail", "Generic failure") try: os.mkdir(os.path.join(self.__project_root, uname)) except FileExistsError as e: pass return ("ok", "") def login(self, uname, pword): """ Log a user in """ record = self.__users.get(uname) if record.hash is None: return ("fail", "failed to login") success = auth.verify(pword, record.hash) if success: uuids = self.__contributors.get_projects(uname) project_ids = [str(uuid_) for uuid_ in uuids] return ("ok", json.dumps(project_ids)) else: return ("fail", "failed to login") def create_project(self, uname, pname, metadata): """ Create a new Composte project. Projects are given unique identifiers, so project names need not be unique. """ metadata = json.loads(metadata) metadata["name"] = pname metadata["owner"] = uname proj = composteProject.ComposteProject(metadata) id_ = str(proj.projectID) hopefully_not_None = self.__users.get(uname) if hopefully_not_None is None: return ("fail", "User {} is not registered".format(uname)) self.write_project(proj) self.__server.info("Creating project {} with name {} for {}".format( id_, metadata["name"], uname)) try: self.__projects.put(id_, pname, uname) except sqlite3.OperationalError as e: self.__server.info("?????????????") raise GenericError("The database is borked") p = self.__projects.get(id_) print(p) # This could then potentially also lock the database... try: self.__contributors.put(uname, id_) except sqlite3.IntegrityError as e: raise e return ("fail", "User {} is not registered".format(uname)) return ("ok", id_) def get_project_over_the_wire(self, pid): """ Retrieve the serialized form of a project for transmission. Currently only used during the initial handshake. """ proj = self.__pool.put(pid, lambda: self.get_project(pid)[1]) self.__pool.remove(pid) if type(proj) == str: return ("fail", "What even is that") return ("ok", json.dumps(proj.serialize())) def get_project(self, pid): """ Fetch a Composte project object for manipulation. Not suitable for use as a top-level handler """ project_entry = self.__projects.get(pid) if project_entry.id == None: return ("fail", "Project not found") pid = project_entry.id owner = project_entry.owner proj = self.read_project(pid) return ("ok", proj) def list_projects_by_user(self, uname): """ Retrieve a list of projects that a user is a collaborator on """ listings = self.__contributors.get(username=uname) listings = [str(project) for project in listings] return ("ok", json.dumps(listings)) def list_contributors_of_project(self, pid): """ Retrieve a list of a project's contributors """ listings = self.__contributors.get(project_id=pid) listings = [str(user) for user in listings] return ("ok", json.dumps(listings)) def compare_versions(self, client_version): """ Compare version hashes """ if client_version != self.version: status = "fail" response = (status, self.version) else: status = "ok" reason = "" response = (status, reason) return response # Utility def write_project(self, project): """ I'm going to cheat for now and dump to the filesystem. Ideally we write to a database, but that requires more work. Either way, that can be hidden in this function """ user = project.metadata["owner"] id_ = str(project.projectID) (metadata, parts, _) = project.serialize() base_path = os.path.join(self.__project_root, user) base_path = os.path.join(base_path, id_) with open(base_path + self.__metadata_extension, "w") as f: f.write(metadata) with open(base_path + self.__project_extension, "w") as f: f.write(parts) def read_project(self, pid): """ We've cheated and the projects live on the filesystem. Ideally we want them in a database, but that's work. Either way, we hide the true locations of projects inside of this function. """ owner = self.__projects.get(pid).owner filename = pid + self.__metadata_extension relpath = os.path.join(owner, filename) fullpath = os.path.join(self.__project_root, relpath) with open(fullpath, "r") as f: metadata = f.read() filename = pid + self.__project_extension relpath = os.path.join(owner, filename) fullpath = os.path.join(self.__project_root, relpath) with open(fullpath, "r") as f: parts = f.read() project = composteProject.deserializeProject((metadata, parts, pid)) # Don't put it into the pool yet, because then we end up with a # use count that will never be 0 again return project # Cookie: uuid def generate_cookie_for(self, user, project): """ We don't bother checking for UUID collisions, since they "don't" happen """ cookie = uuid.uuid4() self.sessions[cookie] = (user, project) return cookie # Session: {user, project_id} # May need login cookies too def cookie_to_session(self, cookie): """ Retrieve the session associated with a cookie """ try: cookie = uuid.UUID(cookie) except ValueError as e: return ("fail", "That doesn't look like a cookie") try: session = self.sessions[cookie] except KeyError as e: return None return session def remove_cookie(self, cookie): """ Remove a cookie and its associated session """ try: cookie = uuid.UUID(cookie) except ValueError as e: return ("fail", "That doesn't look like a cookie") try: del self.sessions[cookie] except KeyError as e: return ("fail", "Who are you") return ("ok", "") def do_update(self, *args): """ Perform a music-related update, deferring to musicWrapper.performMusicFperformMusicFun """ # Use this function to get a project pid_ = None def get_fun(pid): """ Fetch a project from the cache """ # The client musicfuns shouldn't have to worry about how the # server manages the lifetimes of project objects proj = self.__pool.put(pid, lambda: self.get_project(pid)[1]) # We need to steal the pid to release it later pid_ = pid return proj with self.__flushing: try: # We still need to provide a way to get the project reply = musicWrapper.performMusicFun(*args, fetchProject=get_fun) except: print(traceback.format_exc()) return ("fail", "Internal Server Error") return reply # We can't decrement the refcount before now, because we could # cause an early flush otherwise, and then serverside persistence # is breaks. self.__pool.remove(pid_, self.write_project) def subscribe(self, username, pid): """ Subscribe a client to updates for a project. Pins the project in the cache """ # Assert permission contributors = self.__contributors.get(project_id=pid) contributors = [user.uname for user in contributors] if username in contributors: self.__pool.put(pid, lambda: self.get_project(pid)[1]) cookie = self.generate_cookie_for(username, pid) return ("ok", str(cookie)) else: self.__server.debug("{} is not one of {}".format( username, contributors)) return ("fail", "You are not a contributor") def unsubscribe(self, cookie): """ Unsubscribe a client from a project. Unpins the project in the cache """ session = self.cookie_to_session(cookie) if session is None: return ("fail", "You are not subscribed") (user, project_id) = session (status, reason) = self.remove_cookie(cookie) if status == "ok": project = self.__pool.put(project_id, lambda x: self.get_project(x)[1]) pid = project.projectID self.__pool.remove(pid, lambda x: self.write_project(x)) return (status, reason) # Packaged for neatness def get_db_connections(self): """ Open database connections if they are not already open """ dbname = "data/composte.db" if self.__users is None: self.__users = driver.Auth(dbname) if self.__projects is None: self.__projects = driver.Projects(dbname) if self.__contributors is None: self.__contributors = driver.Contributors(dbname) def share(self, pid, new_contributor): """ Add a new user to the list of contributors to a project """ contributors = self.__contributors.get(project_id=pid) user = self.__users.get(new_contributor) # If that's not a known user, fail if user.uname is None: return ("fail", "Who is that") # If they are already a contributor, nothing to do if new_contributor not in contributors: # If that's not a valid project, fail try: self.__contributors.put(new_contributor, pid) except sqlite3.IntegrityError as e: return ("fail", "What project is that") return ("ok", "") # Handlers def __handle(self, _, rpc): """ Dispatch to handle messages """ self.get_db_connections() def fail(*args): return ("fail", "I don't know what you want me to do") def unimplemented(*args): return ("?", "?") rpc_funs = { "register": self.register, "login": self.login, "create_project": self.create_project, "list_projects": self.list_projects_by_user, "get_project": self.get_project_over_the_wire, "subscribe": self.subscribe, "unsubscribe": self.unsubscribe, "update": self.do_update, "handshake": self.compare_versions, "share": self.share, } self.__server.debug(rpc) f = rpc["fName"] do_rpc = rpc_funs.get(f, fail) try: # This is expected to be a tuple of things to send back (status, other) = do_rpc(*rpc["args"]) except GenericError as e: return ("fail", "Internal server error") except: self.__server.error(traceback.format_exc()) return ("fail", "Internal server error (Developer error)") # Only broadcast successful updates if f == "update" and status == "ok": self.__server.broadcast( client.serialize(rpc["fName"], *rpc["args"])) return (status, other) def __preprocess(self, message): """ Deserialize messages for consumption by __handle """ return client.deserialize(message) def __postprocess(self, reply): """ Serialize replies to be sent over the wire """ reply_str = server.serialize(*reply) self.__server.debug(reply_str) return reply_str def stop(self): """ Stop the server elegantly """ self.__server.info("ComposteServer shutting down") with self.__dlock: self.__done = True self.__timer.join() self.__pool.map(self.flush_project) self.__server.stop()
class TestClient(unittest.TestCase): @classmethod def setUpClass(self): try: self.client = Client(constants.MODE_CLIENT, ('127.0.0.1', constants.DEFAULT_PORT)) self.server = Server() self.server.start(constants.DEFAULT_PORT) # Run the test server thread self.testsServerThread = TestsServerThread(self.server) self.testsServerThread.start() except Exception as e: print "Failed to start server: " + str(e) raise e @classmethod def tearDownClass(self): try: self.server.stop() except Exception as e: self.fail("Failed to stop server: " + str(e)) raise 3 def testConncecToServer(self): try: self.client.connect() except Exception as e: print "Failed to connect to server: " + str(e) raise e def testCheckHostname(self): self.assertEqual(self.client.getHostname(), "127.0.0.1") def testHandshake(self): try: self.client.doHandshake() except Exception as e: self.fail(str(e)) def checkEncryptType(self): # Confirm AES is being used self.assertEqual(self.client.sock.encryptType, self.client.sock.AES) def testSendMessageToServer(self): self.client.sendMessage(constants.COMMAND_MSG, CLIENT_TEST_MESSAGE_1) def testReceiveMessageFromServer(self): message = self.client.receiveMessage(constants.COMMAND_MSG) self.assertEqual(message, SERVER_TEST_MESSAGE_1) message = self.client.receiveMessage(constants.COMMAND_MSG) self.assertEqual(message, SERVER_TEST_MESSAGE_2) message = self.client.receiveMessage(constants.COMMAND_MSG) self.assertEqual(message, SERVER_TEST_MESSAGE_3) def testSendUnexpectCommandToServer(self): self.client.sendMessage(constants.COMMAND_REDY) # Server should respond with error command self.client.receiveMessage(constants.COMMAND_ERR) def testDisconnect(self): self.client.disconnect()
def main(log, readlog, only_odometry, sensorFile, odomFile, resultname, mapconfig): initialized = False sensor = None navigation = None robot = None server = None try: #Initialize Sensor if(readlog): sensor = FileXTION(sensorFile) else: sensor = XTION(log) #Initialize Slam if(only_odometry): slam = Deterministic_SLAM(sensor, mapconfig.SIZE_PIXELS, mapconfig.SIZE_METERS) else: slam = My_SLAM(sensor, mapconfig.SIZE_PIXELS, mapconfig.SIZE_METERS, random_seed = SEED) #Initialize Robot if(readlog): robot = FileDrone(odomFile) else: robot = NetworkVehicle(log) robot.initialize() #Open Controll and Map Server server = Server(slam, mapconfig.SIZE_PIXELS, robot) server.start() #Initialize Navigation if(not readlog): navigation = Navigation(slam, mapconfig, robot.getSize(), RELEVANT_LIDARS, SECURITY_DIST_MM, Commands) navigation.start() #Monitors scanno = 0 dist = 0 timePast = 0 trajectory = [] start_sec = time() #Make initial scan scan = sensor.scan() initialized = True #Main loop while(True): scanno += 1 #get command if(readlog): command = None else: command = navigation.update(scan) if(command == None): print "Navigation terminated." break #send command and get odometry velocities = robot.move(command) #check if velocities are valid if(velocities == None): print "Robot terminated." break #update monitors dist += velocities[0] timePast += velocities[2] #get scan scan = sensor.scan() #check if scan is valid if(len(scan)<=0): print "Sensor terminated." break #Update SLAM slam.update(scan, velocities) # Get new position x_mm, y_mm, theta_degrees = slam.getpos() # Add new position to trajectory trajectory.append((x_mm, y_mm)) except KeyboardInterrupt: print "Program stoped!" finally: print "Shutting down." if(sensor != None): sensor.shutdown() if(navigation != None): navigation.stop() if(robot != None): robot.shutdown() if(server != None): server.close() if(initialized): #Print results elapsed_sec = time() - start_sec print('\n%d scans in %f sec = %f scans / sec' % (scanno, elapsed_sec, scanno/elapsed_sec)) print ('Distance traveled:%f mm in %fs' % (dist, timePast)) #generate map mapbytes = createMap(slam, trajectory, mapconfig) # Save map and trajectory as png file mapconfig.safeaspng(mapbytes, resultname)
def test_create_server(self): server = Server() self.assertEqual(len(server.connected_clients), 0)
def main(g=0.4, h=0.4): filename = 'map_%f_%f' % (g, h) """ if(use_odometry): filename += 'withodometry_' if(readlog): filename += 'fromlog_' if(seed==0): filename += 'deterministic' else: filename += ('rmhc_seed' + str(seed)) """ #initialize the asus xtion as sensor if (readlog): sensor = FileXTION("log") else: sensor = XTION() #NetworkSensor() # # Create a CoreSLAM object with laser params and optional robot object slam = My_SLAM(sensor, MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed, g=g, h=h) \ if seed \ else Deterministic_SLAM(sensor, MAP_SIZE_PIXELS, MAP_SIZE_METERS) robot = None #initialiye robot if (use_odometry): navigation = Navigation(slam, MapConfig(), ROBOT_SIZE_METERS, 50, 800, Commands) if (readlog): robot = FileDrone("odometry") else: robot = NetworkVehicle() #Drone() robot.initialize() if (stream): server = Server(slam, MAP_SIZE_PIXELS, robot) server.start() # Start with an empty trajectory of positions trajectory = [] # Start timing start_sec = time() # Loop atexit.register(set_normal_term) set_curses_term() scanno = 0 dist = 0 zeit = 0 if (use_odometry): navigation.start() ##make initial scan scan = sensor.scan() while (True): scanno += 1 if use_odometry: ##navigaiton command = navigation.update(scan) #print command ##odometry velocities = robot.move(command) dist += velocities[0] zeit += velocities[2] print velocities ##lidar scan = sensor.scan() if (len(scan) <= 0): print 'Reader error or end of file.' break # Update SLAM with lidar and velocities slam.update(scan, velocities) else: scan = sensor.scan() if (len(scan) <= 0): print 'Reader error or end of file.' break # Update SLAM with lidar alone slam.update(scan) # Get new position x_mm, y_mm, theta_degrees = slam.getpos() # Add new position to trajectory trajectory.append((x_mm, y_mm)) if kbhit(): break if (use_odometry): robot.shutdown() navigation.stop() # Report elapsed time elapsed_sec = time() - start_sec print('\n%d scans in %f sec = %f scans / sec' % (scanno, elapsed_sec, scanno / elapsed_sec)) print('dist traveled:%f mm in %fs' % (dist, zeit)) mapbytes = createMap(slam, trajectory) # Save map and trajectory as PGM file pgm_save(filename, mapbytes, (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS)) image = cv2.imread(filename, 0) print "Accessing the image.. again. So dirty." print "Saving as .png: ..." cv2.imwrite("test.png", image) if (stream): server.close() print "done"