def init(): """Start listening to incoming connections.""" global _server if _server is not None: return server = QLocalServer(None) # find a free socket name to use for name in ids(): if server.listen(name): break else: # all names failed, try to contact and remove stale file if that fails socket = QLocalSocket() for name in ids(): socket.connectToServer(name) if not socket.waitForConnected(10000): QLocalServer.removeServer(name) if server.listen(name): break else: socket.disconnectFromServer() else: # no ids left, don't listen return app.aboutToQuit.connect(server.close) server.newConnection.connect(slot_new_connection) os.environ["FRESCOBALDI_SOCKET"] = name _server = server
def _send_to_running_instance(self, payload: bytes, pid: int) -> None: from PyQt5.QtCore import QByteArray from PyQt5.QtNetwork import QLocalSocket named_pipe = f"{BUNDLE_IDENTIFIER}.protocol.{pid}" log.debug( f"Opening a local socket to the running instance on {named_pipe} " f"(payload={self.redact_payload(payload)!r})" ) client = QLocalSocket() try: client.connectToServer(named_pipe) if not client.waitForConnected(): log.error(f"Unable to open client socket: {client.errorString()}") return client.write(QByteArray(payload)) client.waitForBytesWritten() client.disconnectFromServer() if client.state() == QLocalSocket.ConnectedState: client.waitForDisconnected() finally: del client log.debug("Successfully closed client socket")
def _send_to_running_instance(self, payload: bytes, pid: int) -> None: from PyQt5.QtCore import QByteArray from PyQt5.QtNetwork import QLocalSocket named_pipe = f"{BUNDLE_IDENTIFIER}.protocol.{pid}" log.debug( f"Opening a local socket to the running instance on {named_pipe} " f"(payload={self.redact_payload(payload)})" ) client = QLocalSocket() try: client.connectToServer(named_pipe) if not client.waitForConnected(): log.error(f"Unable to open client socket: {client.errorString()}") return client.write(QByteArray(payload)) client.waitForBytesWritten() client.disconnectFromServer() if client.state() == QLocalSocket.ConnectedState: client.waitForDisconnected() finally: del client log.debug("Successfully closed client socket")
def _has_legacy_server(name): """Check if there is a legacy server. Args: name: The name to try to connect to. Return: True if there is a server with the given name, False otherwise. """ socket = QLocalSocket() log.ipc.debug("Trying to connect to {}".format(name)) socket.connectToServer(name) err = socket.error() if err != QLocalSocket.UnknownSocketError: log.ipc.debug("Socket error: {} ({})".format(socket.errorString(), err)) os_x_fail = ( sys.platform == "darwin" and socket.errorString() == "QLocalSocket::connectToServer: " "Unknown error 38" ) if err not in [QLocalSocket.ServerNotFoundError, QLocalSocket.ConnectionRefusedError] and not os_x_fail: return True socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(CONNECT_TIMEOUT) return False
def send_to_running_instance(socketname, command, target_arg, *, legacy_name=None, socket=None): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: socketname: The name which should be used for the socket. command: The command to send to the running instance. target_arg: --target command line argument socket: The socket to read data from, or None. legacy_name: The legacy name to first try to connect to. Return: True if connecting was successful, False if no connection was made. """ if socket is None: socket = QLocalSocket() if (legacy_name is not None and _has_legacy_server(legacy_name)): name_to_use = legacy_name else: name_to_use = socketname log.ipc.debug("Connecting to {}".format(name_to_use)) socket.connectToServer(name_to_use) connected = socket.waitForConnected(CONNECT_TIMEOUT) if connected: log.ipc.info("Opening in existing instance") json_data = {'args': command, 'target_arg': target_arg, 'version': qutebrowser.__version__, 'protocol_version': PROTOCOL_VERSION} try: cwd = os.getcwd() except OSError: pass else: json_data['cwd'] = cwd line = json.dumps(json_data) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: raise SocketError("writing to running instance", socket) else: socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(CONNECT_TIMEOUT) return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): raise SocketError("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
def init(): """Start listening to incoming connections.""" global _server if _server is not None: return server = QLocalServer(None) # find a free socket name to use for name in ids(): if server.listen(name): break else: # all names failed, try to contact and remove stale file if that fails socket = QLocalSocket() for name in ids(): socket.connectToServer(name) if not socket.waitForConnected(10000): QLocalServer.removeServer(name) if server.listen(name): break else: socket.disconnectFromServer() else: # no ids left, don't listen return app.aboutToQuit.connect(server.close) server.newConnection.connect(slot_new_connection) os.environ["FRESCOBALDI_SOCKET"] = name _server = server
def _has_legacy_server(name): """Check if there is a legacy server. Args: name: The name to try to connect to. Return: True if there is a server with the given name, False otherwise. """ socket = QLocalSocket() log.ipc.debug("Trying to connect to {}".format(name)) socket.connectToServer(name) err = socket.error() if err != QLocalSocket.UnknownSocketError: log.ipc.debug("Socket error: {} ({})".format( socket.errorString(), err)) os_x_fail = (sys.platform == 'darwin' and socket.errorString() == 'QLocalSocket::connectToServer: ' 'Unknown error 38') if err not in [QLocalSocket.ServerNotFoundError, QLocalSocket.ConnectionRefusedError] and not os_x_fail: return True socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(CONNECT_TIMEOUT) return False
def sendMessage(self, message): assert (self._isRunning) if self.isRunning(): socket = QLocalSocket(self) socket.connectToServer(self._key, QIODevice.WriteOnly) if not socket.waitForConnected(self._timeout): return False socket.write(message.encode('utf-8')) if not socket.waitForBytesWritten(self._timeout): return False socket.disconnectFromServer() return True return False
def sendNotification(self, message): if self.isRunning(): socket = QLocalSocket(self) socket.connectToServer(self._key, QIODevice.WriteOnly) if not socket.waitForConnected(self._timeout): print(socket.errorString()) return False if not isinstance(message, bytes): message = message.encode('utf-8') socket.write(message) if not socket.waitForBytesWritten(self._timeout): print(socket.errorString()) return False socket.disconnectFromServer() return True return False
class InstanceHandler(QObject): """ Makes sure that only one instance of this application can be run. """ received = pyqtSignal(str) def __init__(self, parent, name): super(__class__, self).__init__(parent) self._parent = parent self._name = name self._timeout = 1000 self._socket = QLocalSocket(self) self._socket.connectToServer(self._name) self._is_already_running = self._socket.waitForConnected(self._timeout) if not self.isAlreadyRunning(): self._server = QLocalServer(self) self._server.newConnection.connect(self._receive_data) self._server.removeServer(self._name) self._server.listen(self._name) def _send_data(self, data=None): """ Sends model to an server-application. """ if not data: data = "" self._socket.write(data.encode()) self._socket.waitForBytesWritten(self._timeout) self._socket.disconnectFromServer() def _receive_data(self): """ Receives model from an client-application. """ socket = self._server.nextPendingConnection() if socket.waitForReadyRead(self._timeout): # Emit transmitted model. self.received.emit(socket.readAll().data().decode( "utf-8", "surrogateescape")) else: # When no model was transmitted just emit empty string. self.received.emit("") def newTab(self, input): """ Opens a new tab in an already running instance. """ self._send_data(input) def isAlreadyRunning(self) -> bool: """ Returns True when an instance of the application is already running, otherwise False. """ return self._is_already_running
def send_to_running_instance(socketname, command): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: socketname: The name which should be used for the socket. command: The command to send to the running instance. Return: True if connecting was successful, False if no connection was made. """ socket = QLocalSocket() log.ipc.debug("Connecting to {}".format(socketname)) socket.connectToServer(socketname) connected = socket.waitForConnected(100) if connected: log.ipc.info("Opening in existing instance") json_data = {'args': command} try: cwd = os.getcwd() except OSError: pass else: json_data['cwd'] = cwd line = json.dumps(json_data) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: _socket_error("writing to running instance", socket) else: socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(100) return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): _socket_error("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
def _send_to_running_instance(self, payload: bytes) -> bool: from PyQt5.QtCore import QByteArray from PyQt5.QtNetwork import QLocalSocket log.debug( f"Opening local socket to send to the running instance (payload={payload})" ) client = QLocalSocket() client.connectToServer("com.nuxeo.drive.protocol") if not client.waitForConnected(): log.error(f"Unable to open client socket: {client.errorString()}") return 0 client.write(QByteArray(payload)) client.waitForBytesWritten() client.disconnectFromServer() client.waitForDisconnected() del client log.debug("Successfully closed client socket")
class Client: def __init__(self): self.socket = QLocalSocket() self.socket.setServerName(piony.G_SOCKET_NAME) self.socket.error.connect(self.displayError) self.socket.disconnected.connect(self.socket.deleteLater) def _log_(self, text, *args): logger.info(self.__class__.__qualname__ + ': ' + text, *args) def connect(self): self.socket.abort() self._log_("connection attempt") self.socket.connectToServer() def send(self, argv): data = QByteArray() out = QDataStream(data, QIODevice.WriteOnly) out.setVersion(QDataStream.Qt_5_0) out.writeQVariant(argv) self._log_("writes: %s", str(data)) self.socket.write(data) self.socket.flush() self.socket.disconnectFromServer() def displayError(self, err): msg = { QLocalSocket.ServerNotFoundError: "The host was not found. Check the host name and port.", QLocalSocket.ConnectionRefusedError: "The connection was refused by the peer. " "Check server is running, it's host and port.", QLocalSocket.PeerClosedError: "Peer was closed", # None, }.get(err, "Client error: {}.".format(self.socket.errorString())) self._log_(msg)
class SingleApplicationClient(object): """ Class implementing the single application client base class. """ def __init__(self, name): """ Constructor @param name name of the local server to connect to (string) """ self.name = name self.connected = False def connect(self, timeout=10000): """ Public method to connect the single application client to its server. @param timeout connection timeout value in milliseconds @type int @return value indicating success or an error number. Value is one of: <table> <tr><td>0</td><td>No application is running</td></tr> <tr><td>1</td><td>Application is already running</td></tr> </table> """ self.sock = QLocalSocket() self.sock.connectToServer(self.name) if self.sock.waitForConnected(timeout): self.connected = True return 1 else: err = self.sock.error() if err == QLocalSocket.ServerNotFoundError: return 0 else: return -err def disconnect(self): """ Public method to disconnect from the Single Appliocation server. """ self.sock.disconnectFromServer() self.connected = False def processArgs(self, args): """ Public method to process the command line args passed to the UI. <b>Note</b>: This method must be overridden by subclasses. @param args command line args (list of strings) @exception RuntimeError raised to indicate that this method must be implemented by a subclass """ raise RuntimeError("'processArgs' must be overridden") def sendCommand(self, command, arguments): """ Public method to send the command to the application server. @param command command to be sent to the server @type str @param arguments list of command arguments @type list of str """ if self.connected: commandDict = { "command": command, "arguments": arguments, } self.sock.write(QByteArray( "{0}\n".format(json.dumps(commandDict)).encode() )) self.sock.flush() def errstr(self): """ Public method to return a meaningful error string for the last error. @return error string for the last error (string) """ return self.sock.errorString()
class QtSingleApplication(QApplication): """ This class makes sure that we can only start one Tribler application. When a user tries to open a second Tribler instance, the current active one will be brought to front. """ messageReceived = pyqtSignal(unicode) def __init__(self, win_id, *argv): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') QApplication.__init__(self, *argv) self._id = win_id self._activation_window = None self._activate_on_message = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() self._outStream = None self._inSocket = None self._inStream = None self._server = None if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't, at least not properly. # Cleanup any past, crashed server. error = self._outSocket.error() logfunc(LOGVARSTR % ('self._outSocket.error()', error)) if error == QLocalSocket.ConnectionRefusedError: logfunc('received QLocalSocket.ConnectionRefusedError; ' + \ 'removing server.') self.close() QLocalServer.removeServer(self._id) self._outSocket = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._on_new_connection) logfunc(sys._getframe().f_code.co_name + '(): returning') def close(self): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') if self._inSocket: self._inSocket.disconnectFromServer() if self._outSocket: self._outSocket.disconnectFromServer() if self._server: self._server.close() logfunc(sys._getframe().f_code.co_name + '(): returning') def is_running(self): return self._isRunning def get_id(self): return self._id def activation_window(self): return self._activation_window def set_activation_window(self, activation_window, activate_on_message=True): self._activation_window = activation_window self._activate_on_message = activate_on_message def activate_window(self): if not self._activation_window: return self._activation_window.setWindowState( self._activation_window.windowState() & ~Qt.WindowMinimized) self._activation_window.raise_() def send_message(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _on_new_connection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._on_ready_read) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._on_ready_read) if self._activate_on_message: self.activate_window() def _on_ready_read(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
def qlocalsocket(qapp): socket = QLocalSocket() yield socket socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(1000)
def qlocalsocket(qapp): socket = QLocalSocket() yield socket socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(1000)
class SingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, appid, *argv): super(SingleApplication, self).__init__(*argv) self._appid = appid self._activationWindow = None self._activateOnMessage = False self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._appid) self._isRunning = self._outSocket.waitForConnected() self._outStream = None self._inSocket = None self._inStream = None self._server = None self.settings = QSettings(SingleApplication.getSettingsPath(), QSettings.IniFormat) self.singleInstance = self.settings.value('singleInstance', 'on', type=str) in {'on', 'true'} if self._isRunning and self.singleInstance: self._outStream = QTextStream(self._outSocket) for a in argv[0][1:]: a = os.path.join(os.getcwd(), a) if os.path.isfile(a): self.sendMessage(a) break sys.exit(0) else: error = self._outSocket.error() if error == QLocalSocket.ConnectionRefusedError: self.close() QLocalServer.removeServer(self._appid) self._outSocket = None self._server = QLocalServer() self._server.listen(self._appid) self._server.newConnection.connect(self._onNewConnection) def close(self): if self._inSocket: self._inSocket.disconnectFromServer() if self._outSocket: self._outSocket.disconnectFromServer() if self._server: self._server.close() @staticmethod def getSettingsPath() -> str: if sys.platform == 'win32': settings_path = os.path.join(QDir.homePath(), 'AppData', 'Local', 'vidcutter') elif sys.platform == 'darwin': settings_path = os.path.join(QDir.homePath(), 'Library', 'Preferences', 'vidcutter') else: if QFileInfo(__file__).absolutePath().startswith('/app/'): settings_path = QProcessEnvironment.systemEnvironment().value( 'XDG_CONFIG_HOME', '') if not len(settings_path): settings_path = os.path.join(QDir.homePath(), '.var', 'app', vidcutter.__desktopid__, 'config') else: settings_path = os.path.join(QDir.homePath(), '.config', 'vidcutter') return os.path.join(settings_path, 'vidcutter.ini') def isRunning(self): return self._isRunning def appid(self): return self._appid def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False # noinspection PyUnresolvedReferences self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class SingleApplicationClient(object): """ Class implementing the single application client base class. """ def __init__(self, name): """ Constructor @param name name of the local server to connect to (string) """ self.name = name self.connected = False def connect(self): """ Public method to connect the single application client to its server. @return value indicating success or an error number. Value is one of: <table> <tr><td>0</td><td>No application is running</td></tr> <tr><td>1</td><td>Application is already running</td></tr> </table> """ self.sock = QLocalSocket() self.sock.connectToServer(self.name) if self.sock.waitForConnected(10000): self.connected = True return 1 else: err = self.sock.error() if err == QLocalSocket.ServerNotFoundError: return 0 else: return -err def disconnect(self): """ Public method to disconnect from the Single Appliocation server. """ self.sock.disconnectFromServer() self.connected = False def processArgs(self, args): """ Public method to process the command line args passed to the UI. <b>Note</b>: This method must be overridden by subclasses. @param args command line args (list of strings) @exception RuntimeError raised to indicate that this method must be implemented by a subclass """ raise RuntimeError("'processArgs' must be overridden") def sendCommand(self, cmd): """ Public method to send the command to the application server. @param cmd command to be sent (string) """ if self.connected: self.sock.write(cmd) self.sock.flush() def errstr(self): """ Public method to return a meaningful error string for the last error. @return error string for the last error (string) """ return self.sock.errorString()
class QtSingleApplication(QApplication): """ This class makes sure that we can only start one Tribler application. When a user tries to open a second Tribler instance, the current active one will be brought to front. """ messageReceived = pyqtSignal(str) def __init__(self, win_id, *argv): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') QApplication.__init__(self, *argv) self._id = win_id self._activation_window = None self._activate_on_message = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() self._outStream = None self._inSocket = None self._inStream = None self._server = None if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't, at least not properly. # Cleanup any past, crashed server. error = self._outSocket.error() logfunc(LOGVARSTR % ('self._outSocket.error()', error)) if error == QLocalSocket.ConnectionRefusedError: logfunc('received QLocalSocket.ConnectionRefusedError; removing server.') self.close() QLocalServer.removeServer(self._id) self._outSocket = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._on_new_connection) logfunc(sys._getframe().f_code.co_name + '(): returning') def close(self): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') if self._inSocket: self._inSocket.disconnectFromServer() if self._outSocket: self._outSocket.disconnectFromServer() if self._server: self._server.close() logfunc(sys._getframe().f_code.co_name + '(): returning') def is_running(self): return self._isRunning def get_id(self): return self._id def activation_window(self): return self._activation_window def set_activation_window(self, activation_window, activate_on_message=True): self._activation_window = activation_window self._activate_on_message = activate_on_message def activate_window(self): if not self._activation_window: return self._activation_window.setWindowState(self._activation_window.windowState() & ~Qt.WindowMinimized) self._activation_window.raise_() def send_message(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _on_new_connection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._on_ready_read) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._on_ready_read) if self._activate_on_message: self.activate_window() def _on_ready_read(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)