Beispiel #1
0
 def receive(self):
     while True:
         frame = self._parser.get()
         if frame is not None:
             return frame
         try:
             data = self._socket.recv(self.READ_SIZE)
             if not data:
                 raise StompConnectionError('No more data')
         except (IOError, StompConnectionError) as e:
             self.disconnect()
             raise StompConnectionError('Connection closed [%s]' % e)
         self._parser.add(data)
Beispiel #2
0
 def disconnect(self):
     try:
         self._socket and self._socket.close()
     except IOError as e:
         raise StompConnectionError('Could not close connection cleanly [%s]' % e)
     finally:
         self._socket = None
Beispiel #3
0
    def connect(self,
                headers=None,
                versions=None,
                host=None,
                heartBeats=None,
                connectTimeout=None,
                connectedTimeout=None):
        """Establish a connection to a STOMP broker. If the wire-level connect fails, attempt a failover according to the settings in the client's :class:`~.StompConfig` object. If there are active subscriptions in the :attr:`~.sync.client.Stomp.session`, replay them when the STOMP connection is established.
        
        :param versions: The STOMP protocol versions we wish to support. The default behavior (:obj:`None`) is the same as for the :func:`~.commands.connect` function of the commands API, but the highest supported version will be the one you specified in the :class:`~.StompConfig` object. The version which is valid for the connection about to be initiated will be stored in the :attr:`~.sync.client.Stomp.session`.
        :param connectTimeout: This is the time (in seconds) to wait for the wire-level connection to be established. If :obj:`None`, we will wait indefinitely.
        :param connectedTimeout: This is the time (in seconds) to wait for the STOMP connection to be established (that is, the broker's **CONNECTED** frame to arrive). If :obj:`None`, we will wait indefinitely.
        
        **Example:**
        
        >>> client = Stomp(StompConfig('tcp://localhost:61613', version=StompSpec.VERSION_1_1))
        >>> client.connect()
        >>> client.session.version
        '1.1'
        >>> client.disconnect()
        >>> client.connect(versions=[StompSpec.VERSION_1_0])
        >>> client.session.version
        '1.0'
        >>> client.disconnect()
        >>> client.session.version
        '1.1'
        
        .. seealso :: The :mod:`.protocol.failover` and :mod:`.protocol.session` modules for the details of subscription replay and failover transport.
        """
        try:  # preserve existing connection
            self._transport
        except StompConnectionError:
            pass
        else:
            raise StompConnectionError('Already connected to %s' %
                                       self._transport)

        try:
            for (broker, connectDelay) in self._failover:
                transport = self._transportFactory(broker['host'],
                                                   broker['port'])
                if connectDelay:
                    self.log.debug('Delaying connect attempt for %d ms' %
                                   int(connectDelay * 1000))
                    time.sleep(connectDelay)
                self.log.info('Connecting to %s ...' % transport)
                try:
                    transport.connect(connectTimeout)
                except StompConnectionError as e:
                    self.log.warning('Could not connect to %s [%s]' %
                                     (transport, e))
                else:
                    self.log.info('Connection established')
                    self._transport = transport
                    self._connect(headers, versions, host, heartBeats,
                                  connectedTimeout)
                    break
        except StompConnectionError as e:
            self.log.error('Reconnect failed [%s]' % e)
            raise
Beispiel #4
0
 def _protocol(self):
     try:
         protocol = self.__protocol
     except AttributeError:
         self._protocol = None
         return self._protocol
     if not protocol:
         raise StompConnectionError('Not connected')
     return protocol
Beispiel #5
0
 def connect(self, timeout=None):
     kwargs = {} if (timeout is None) else {'timeout': timeout}
     try:
         self._socket = socket.create_connection((self.host, self.port),
                                                 **kwargs)
     except IOError as e:
         raise StompConnectionError('Could not establish connection [%s]' %
                                    e)
     self._parser.reset()
Beispiel #6
0
    def connect(self, timeout=None):
        """ Allow older versions of ssl module, allow http proxy connections """
        LOG.debug("stomp_transport.connect()")
        ssl_params = None
        if isinstance(self.sslContext, dict):
            # This is actually a dictionary of ssl parameters for wrapping the socket
            ssl_params = self.sslContext
            self.sslContext = None

        try:
            if self.proxy_host:
                try:
                    # Don't try to import this unless we need it
                    import socks
                except ImportError:
                    raise ImportError(
                        "No http proxy support available.  Is pysocks installed?"
                    )

                LOG.info("Connecting through proxy %s", self.proxy_host)
                self._socket = socks.socksocket()
                self._socket.set_proxy(socks.HTTP,
                                       self.proxy_host,
                                       self.proxy_port,
                                       True,
                                       username=self.proxy_user,
                                       password=self.proxy_password)
            else:
                self._socket = socket.socket()

            self._socket.settimeout(timeout)
            self._socket.connect((self.host, self.port))

            if ssl_params:
                # For cases where we don't have a modern SSLContext (so no SNI)
                cert_required = ssl.CERT_REQUIRED if ssl_params[
                    "ca_certs"] else ssl.CERT_NONE
                self._socket = ssl.wrap_socket(
                    self._socket,
                    keyfile=ssl_params['key_file'],
                    certfile=ssl_params['cert_file'],
                    cert_reqs=cert_required,
                    ca_certs=ssl_params['ca_certs'],
                    ssl_version=ssl_params['ssl_version'])
                if cert_required:
                    LOG.info("Performing manual hostname check")
                    cert = self._socket.getpeercert()
                    self.match_hostname(cert, self.host)

            if self.sslContext:
                self._socket = self.sslContext.wrap_socket(
                    self._socket, server_hostname=self.host)

        except IOError as e:
            raise StompConnectionError('Could not establish connection [%s]' %
                                       e)
        self._parser.reset()
Beispiel #7
0
 def _transport(self):
     transport = self.__transport
     if not transport:
         raise StompConnectionError('Not connected')
     try:
         transport.canRead(0)
     except Exception as e:
         self.close(flush=False)
         raise e
     return transport
Beispiel #8
0
 def connect(self, timeout=None):
     try:
         self._socket = socket.socket()
         self._socket.settimeout(timeout)
         if self.sslContext:
             self._socket = self.sslContext.wrap_socket(self._socket, server_hostname=self.host)
         self._socket.connect((self.host, self.port))
     except IOError as e:
         raise StompConnectionError('Could not establish connection [%s]' % e)
     self._parser.reset()
Beispiel #9
0
 def connect(self, timeout=None):
     kwargs = {} if (timeout is None) else {'timeout': timeout}
     try:
         self._socket = socket.create_connection((self.host, self.port),
                                                 **kwargs)
         if self.protocol == Broker.PROTOCOL_SSL:
             self._socket = sslWrapSocket(self._socket,
                                          sslContext=self.sslContext,
                                          host=self.host)
     except IOError as e:
         raise StompConnectionError('Could not establish connection [%s]' %
                                    e)
     self._parser.reset()
Beispiel #10
0
    def connect(self,
                headers=None,
                versions=None,
                host=None,
                heartBeats=None,
                connectTimeout=None,
                connectedTimeout=None):
        """connect(headers=None, versions=None, host=None, heartBeats=None, connectTimeout=None, connectedTimeout=None)

        Establish a connection to a STOMP broker. If the wire-level connect fails, attempt a failover according to the settings in the client's :class:`~.StompConfig` object. If there are active subscriptions in the :attr:`~.async.client.Stomp.session`, replay them when the STOMP connection is established. This method returns a :class:`twisted.internet.defer.Deferred` object which calls back with :obj:`self` when the STOMP connection has been established and all subscriptions (if any) were replayed. In case of an error, it will err back with the reason of the failure.

        :param versions: The STOMP protocol versions we wish to support. The default behavior (:obj:`None`) is the same as for the :func:`~.commands.connect` function of the commands API, but the highest supported version will be the one you specified in the :class:`~.StompConfig` object. The version which is valid for the connection about to be initiated will be stored in the :attr:`~.async.client.Stomp.session`.
        :param connectTimeout: This is the time (in seconds) to wait for the wire-level connection to be established. If :obj:`None`, we will wait indefinitely.
        :param connectedTimeout: This is the time (in seconds) to wait for the STOMP connection to be established (that is, the broker's **CONNECTED** frame to arrive). If :obj:`None`, we will wait indefinitely.

        .. note :: Only one connect attempt may be pending at a time. Any other attempt will result in a :class:`~.StompAlreadyRunningError`.

        .. seealso :: The :mod:`.protocol.failover` and :mod:`~.protocol.session` modules for the details of subscription replay and failover transport.
        """
        frame = self.session.connect(self._config.login, self._config.passcode,
                                     headers, versions, host, heartBeats)

        try:
            self._protocol
        except:
            pass
        else:
            raise StompConnectionError('Already connected')

        for listener in self._listenersFactory():
            self.add(listener)

        try:
            self._protocol = yield self._protocolCreator.connect(
                connectTimeout, self._onFrame, self._onConnectionLost)
        except Exception as e:
            self.log.error('Endpoint connect failed')
            raise

        try:
            self.sendFrame(frame)
            yield self._notify(
                lambda l: l.onConnect(self, frame, connectedTimeout))

        except Exception as e:
            self.disconnect(failure=e)
            yield self.disconnected

        yield self._replay()

        defer.returnValue(self)
Beispiel #11
0
    def disconnect(self):
        try:
            self._poll and self._socket and self._poll.unregister(self._socket)
        except:
            pass
        finally:
            self._poll = None

        try:
            self._socket and self._socket.close()
        except IOError as e:
            raise StompConnectionError(
                'Could not close connection cleanly [%s]' % e)
        finally:
            self._socket = None
Beispiel #12
0
    def onConnectionLost(self, connection, reason):
        self.log.info('Disconnected: %s' % reason.getErrorMessage())
        if not self._disconnecting:
            self._disconnectReason = StompConnectionError('Unexpected connection loss [%s]' % reason.getErrorMessage())

        connection.remove(self)
        connection.session.close(flush=not self._disconnectReason)

        if self._disconnectReason:
            if self.log.isEnabledFor(logging.DEBUG):
                self.log.debug('Calling disconnected errback: %s' % self._disconnectReason)
            connection.disconnected.errback(self._disconnectReason)
        else:
            if self.log.isEnabledFor(logging.DEBUG):
                self.log.debug('Calling disconnected callback')
            connection.disconnected.callback(None)
Beispiel #13
0
    def connect(self,
                headers=None,
                versions=None,
                host=None,
                heartBeats=None,
                connectTimeout=None,
                connectedTimeout=None):
        """connect(headers=None, versions=None, host=None, heartBeats=None, connectTimeout=None, connectedTimeout=None)

        Establish a connection to a STOMP broker. If the wire-level connect fails, attempt a failover according to the settings in the client's :class:`~.StompConfig` object. If there are active subscriptions in the :attr:`~.twisted.client.Stomp.session`, replay them when the STOMP connection is established.

        :param versions: The STOMP protocol versions we wish to support. The default behavior (:obj:`None`) is the same as for the :func:`~.commands.connect` function of the commands API, but the highest supported version will be the one you specified in the :class:`~.StompConfig` object. The version which is valid for the connection about to be initiated will be stored in the :attr:`~.twisted.client.Stomp.session`.
        :param connectTimeout: This is the time (in seconds) to wait for the wire-level connection to be established. If :obj:`None`, we will wait indefinitely.
        :param connectedTimeout: This is the time (in seconds) to wait for the STOMP connection to be established (that is, the broker's **CONNECTED** frame to arrive). If :obj:`None`, we will wait indefinitely.

        .. seealso :: The :mod:`.protocol.failover` and :mod:`~.protocol.session` modules for the details of subscription replay and failover transport.
        """
        try:
            self._protocol
        except:
            pass
        else:
            raise StompConnectionError('Already connected')

        for listener in self._listenersFactory():
            self.add(listener)

        try:
            self._protocol = yield self._protocolCreator.connect(
                connectTimeout, self._onFrame, self._onConnectionLost)
        except:
            self._onConnectionLost(failure.Failure())
            yield self.disconnected

        try:
            frame = self.session.connect(self._config.login,
                                         self._config.passcode, headers,
                                         versions, host, heartBeats)
            self.sendFrame(frame)
            yield self._notify(
                lambda l: l.onConnect(self, frame, connectedTimeout))
        except Exception as e:
            self.disconnect(reason=e)
            yield self.disconnected

        yield self._replay()
Beispiel #14
0
 def _beat(self, connection, which):
     try:
         self._heartBeats.pop(which).cancel()
     except:
         pass
     if not connection:
         return
     remaining = self._beatRemaining(connection.session, which)
     if remaining < 0:
         return
     if not remaining:
         if which == 'client':
             connection.sendFrame(connection.session.beat())
             remaining = self._beatRemaining(connection.session, which)
         else:
             connection.disconnect(reason=StompConnectionError('Server heart-beat timeout'))
             return
     self._heartBeats[which] = reactor.callLater(remaining, self._beat, connection, which) # @UndefinedVariable
Beispiel #15
0
 def _check(self):
     if not self._connected():
         raise StompConnectionError('Not connected')
Beispiel #16
0
 def _write(self, data):
     self._check()
     try:
         self._socket.sendall(data)
     except IOError as e:
         raise StompConnectionError('Could not send to connection [%s]' % e)
Beispiel #17
0
 def onConnectionLost(self, connection, reason):  # @UnusedVariable
     self.log.info('Disconnected: %s' % reason.getErrorMessage())
     if not self._disconnecting:
         self._disconnectReason = StompConnectionError(
             'Unexpected connection loss [%s]' % reason.getErrorMessage())
Beispiel #18
0
    def connect(self, timeout=None):
        """ Allow older versions of ssl module, allow http proxy connections """
        LOG.debug("stomp_transport.connect()")
        ssl_params = None
        if isinstance(self.sslContext, dict):
            # This is actually a dictionary of ssl parameters for wrapping the socket
            ssl_params = self.sslContext
            self.sslContext = None

        proxy_details = helpers.get_and_parse_proxy_env_var(
            constants.ENV_HTTPS_PROXY)
        proxy_type = socks.HTTP

        if helpers.is_env_proxies_set() and proxy_details:

            if helpers.is_in_no_proxy(self.host):
                self.proxy_host = None
                self.proxy_port = None
                self.proxy_user = None
                self.proxy_password = None

            else:
                self.proxy_host = proxy_details.get("hostname", "")
                self.proxy_port = proxy_details.get("port")
                self.proxy_user = proxy_details.get("username", "")
                self.proxy_password = proxy_details.get("password", "")

        try:
            if self.proxy_host:
                LOG.info("Connecting through proxy %s", self.proxy_host)
                self._socket = socks.socksocket()
                self._socket.set_proxy(proxy_type,
                                       self.proxy_host,
                                       self.proxy_port,
                                       True,
                                       username=self.proxy_user,
                                       password=self.proxy_password)
            else:
                self._socket = socket.socket()

            self._socket.settimeout(timeout)
            self._socket.connect((self.host, self.port))

            if ssl_params:
                # For cases where we don't have a modern SSLContext (so no SNI)
                cert_required = ssl.CERT_REQUIRED if ssl_params[
                    "ca_certs"] else ssl.CERT_NONE
                self._socket = ssl.wrap_socket(
                    self._socket,
                    keyfile=ssl_params['key_file'],
                    certfile=ssl_params['cert_file'],
                    cert_reqs=cert_required,
                    ca_certs=ssl_params['ca_certs'],
                    ssl_version=ssl_params['ssl_version'])
                if cert_required:
                    LOG.info("Performing manual hostname check")
                    cert = self._socket.getpeercert()
                    self.match_hostname(cert, self.host)

            if self.sslContext:
                self._socket = self.sslContext.wrap_socket(
                    self._socket, server_hostname=self.host)

        except IOError as e:
            raise StompConnectionError('Could not establish connection [%s]' %
                                       e)
        self._parser.reset()