def connect(self): ''' Attempts to connect to the server. Returns whether the connection succeeded or not. ''' try: # Create a socket and try to connect to a server. self._socket = socket.socket() self._socket.connect((self._host, self._port)) # Package our Shotgun auth data to then send to the server. authData = {common.AUTH_SERVER: self._sg.config.server, common.AUTH_SCRIPT: self._sg.config.script_name, common.AUTH_KEY: self._sg.config.api_key} dynasocket.send(self._socket, str(authData)) # Get back a message as to whether or not we have succeeded. msg = dynasocket.recv(self._socket) if msg == common.CONNECT_SUCCESS_MSG: self._connected = True elif msg == common.CONNECT_FAIL_MSG: self._connected = False except socket.error: logMsg = common.getLogMessage("Could not connect to server", (self._host, self._port)) logger.warning(logMsg) return self._connected
def sendCommand(self, func, *args, **kwargs): ''' Sends the Shotgun call over to the server to be performed. ''' if not self._connected: logMsg = "client is not connected to a server" logger.critical(logMsg) raise ConnectionError(logMsg) # Assemble our function data and send through the socket. funcData = {common.FUNC_NAME: func.__name__, common.ARGS: args, common.KWARGS: kwargs} dynasocket.send(self._socket, str(funcData)) # Receive back the results that the server got from Shotgun msg = dynasocket.recv(self._socket) return ast.literal_eval(msg)
def run(self): ''' Starts the server watching for messages. This will receive messages and handle them appropriately. Messages are either clients connecting or disconnecting, or a Shotgun transaction request coming in from a client. ''' self._isRunning = True self._needsReInit = True logMsg = common.getLogMessage("DoubleBarrel server started", (self._host, self._port)) self.logger().info(logMsg) while self._isRunning: # Get all of our sockets that have communications occurring. sread, swrite, sexc = select.select(self._clients, [], [], 0.1) #@UnusedVariable for sock in sread: # If the signal is coming from the server socket. if sock == self._socket: # A client is trying to connect. self.acceptNewClient() else: try: # Otherwise, we are receiving a message from the client. msg = dynasocket.recv(sock) if msg: # If we have a message, it is a Shotgun transaction. logMsg = common.getLogMessage("Message received", sock, Message=msg) self.logger().info(logMsg) # Convert our message into a dictionary we can use. funcData = ast.literal_eval(msg) while 1: # Loop until we have a free thread available. if threading.activeCount() < self._maxThreads: ShotgunCommandThread(self._sg, funcData, sock).start() break else: # If there is no message, our client has disconnected. self.disconnectClient(sock) except: self._hasErrored = True self.disconnectClient(sock) # Kill the socket since we are no longer in the loop. logMsg = common.getLogMessage("Stopping server", self._socket) self._socket.close()
def acceptNewClient(self): ''' Connects a new client by accepting its request and then authorizes it. If it passes authorization, it will add it to the active clients list so we start receiving messages from it. ''' newsock, (host, port) = self._socket.accept() #@UnusedVariable # Create a variable to keep track of if we have failed the connection. failed = False # Get our authorization data. msg = dynasocket.recv(newsock) if msg: authData = ast.literal_eval(msg) server = authData.get(common.AUTH_SERVER) script_name = authData.get(common.AUTH_SCRIPT) api_key = authData.get(common.AUTH_KEY) else: failed = True # Check that our auth data matches our current Shotgun object. if server == self._sg.config.server \ and script_name == self._sg.config.script_name \ and api_key == self._sg.config.api_key: self._clients.append(newsock) self.logger().info(common.getLogMessage("Client Connected", newsock)) dynasocket.send(newsock, common.CONNECT_SUCCESS_MSG) return True else: failed = True if failed: dynasocket.send(newsock, common.CONNECT_FAIL_MSG) newsock.close() return False