Beispiel #1
0
class STOMP11(STOMP10):

    SUPPORTED_VERSIONS = {"1.0", "1.1"}

    def __init__(self, engine, send_heartbeat_interval=100, receive_heartbeat_interval=100, *args, **kwargs):
        super(STOMP11, self).__init__(engine)
        self.last_hb = datetime.datetime.now()
        self.last_hb_sent = datetime.datetime.now()
        self.timer = CoilThreadingTimer()

        # flags to control heartbeating
        self.send_hb = self.receive_hb = False

        self.send_heartbeat_interval = datetime.timedelta(milliseconds=send_heartbeat_interval)
        self.receive_heartbeat_interval = datetime.timedelta(milliseconds=receive_heartbeat_interval)

    def enable_heartbeat(self, cx, cy, response):
        if self.send_heartbeat_interval and cy:
            self.send_heartbeat_interval = max(self.send_heartbeat_interval, datetime.timedelta(milliseconds=cy))
            self.timer.schedule(
                max(self.send_heartbeat_interval, datetime.timedelta(milliseconds=cy)).total_seconds(),
                self.send_heartbeat,
            )
        if self.receive_heartbeat_interval and cx:
            self.timer.schedule(
                max(self.send_heartbeat_interval, datetime.timedelta(milliseconds=cx)).total_seconds(),
                self.receive_heartbeat,
            )
        self.timer.start()
        response.headers["heart-beat"] = "{0},{1}".format(
            int(self.send_heartbeat_interval.microseconds / 1000),
            int(self.receive_heartbeat_interval.microseconds / 1000),
        )

    def disable_heartbeat(self):
        self.timer.stop()

    def send_heartbeat(self):
        # screw it, just send an error frame
        self.engine.connection.send_frame(ErrorFrame("heartbeat"))

    def receive_heartbeat(self):
        ago = datetime.datetime.now() - self.last_hb
        if ago > self.receive_heartbeat_interval:
            self.engine.log.debug("No heartbeat was received for {0} seconds".format(ago.total_seconds()))
            self.engine.unbind()

    def connect(self, frame, response=None):
        connected_frame = Frame(frames.CONNECTED)
        self._negotiate_protocol(frame, connected_frame)
        heart_beat = frame.headers.get("heart-beat", "0,0")
        if heart_beat:
            self.enable_heartbeat(*map(int, heart_beat.split(",")), response=connected_frame)
        super(STOMP11, self).connect(frame, response=connected_frame)

    def nack(self, frame):
        """
        Handles the NACK command: Unacknowledges receipt of a message.
        For now, this is just a placeholder to implement this version of the protocol
        """
        if not frame.headers.get("message-id"):
            raise ProtocolError("No message-id specified for NACK command.")
        if not frame.headers.get("subscription"):
            raise ProtocolError("No subscription specified for NACK command.")

    def _negotiate_protocol(self, frame, response):
        client_versions = frame.headers.get("accept-version")
        if not client_versions:
            raise ProtocolError("No version specified")
        common = set(client_versions.split(",")) & self.SUPPORTED_VERSIONS
        if not common:
            versions = ",".join(self.SUPPORTED_VERSIONS)
            self.engine.connection.send_frame(
                Frame(
                    frames.ERROR,
                    headers={"version": versions, "content-type": frames.TEXT_PLAIN},
                    body="Supported protocol versions are {0}".format(versions),
                )
            )
        else:
            response.headers["version"] = max(common)
            protocol_class = PROTOCOL_MAP[response.headers["version"]]
            if type(self) is not protocol_class:
                self.engine.protocol = protocol_class(self.engine)
                self.engine.protocol.connect(frame, response=response)
Beispiel #2
0
class STOMP11(STOMP10):

    SUPPORTED_VERSIONS = {'1.0', '1.1'}

    def __init__(self,
                 engine,
                 send_heartbeat_interval=100,
                 receive_heartbeat_interval=100,
                 *args,
                 **kwargs):
        super(STOMP11, self).__init__(engine)
        self.last_hb = datetime.datetime.now()
        self.last_hb_sent = datetime.datetime.now()
        self.timer = CoilThreadingTimer()

        # flags to control heartbeating
        self.send_hb = self.receive_hb = False

        self.send_heartbeat_interval = datetime.timedelta(
            milliseconds=send_heartbeat_interval)
        self.receive_heartbeat_interval = datetime.timedelta(
            milliseconds=receive_heartbeat_interval)

    def enable_heartbeat(self, cx, cy, response):
        if self.send_heartbeat_interval and cy:
            self.send_heartbeat_interval = max(
                self.send_heartbeat_interval,
                datetime.timedelta(milliseconds=cy))
            self.timer.schedule(
                max(self.send_heartbeat_interval,
                    datetime.timedelta(milliseconds=cy)).total_seconds(),
                self.send_heartbeat)
        if self.receive_heartbeat_interval and cx:
            self.timer.schedule(
                max(self.send_heartbeat_interval,
                    datetime.timedelta(milliseconds=cx)).total_seconds(),
                self.receive_heartbeat)
        self.timer.start()
        response.headers['heart-beat'] = '{0},{1}'.format(
            int(self.send_heartbeat_interval.microseconds / 1000),
            int(self.receive_heartbeat_interval.microseconds / 1000))

    def disable_heartbeat(self):
        self.timer.stop()

    def send_heartbeat(self):
        # screw it, just send an error frame
        self.engine.connection.send_frame(ErrorFrame('heartbeat'))

    def receive_heartbeat(self):
        ago = datetime.datetime.now() - self.last_hb
        if ago > self.receive_heartbeat_interval:
            self.engine.log.debug(
                "No heartbeat was received for {0} seconds".format(
                    ago.total_seconds()))
            self.engine.unbind()

    def connect(self, frame, response=None):
        connected_frame = Frame(frames.CONNECTED)
        self._negotiate_protocol(frame, connected_frame)
        heart_beat = frame.headers.get('heart-beat', '0,0')
        if heart_beat:
            self.enable_heartbeat(*map(int, heart_beat.split(',')),
                                  response=connected_frame)
        super(STOMP11, self).connect(frame, response=connected_frame)

    def nack(self, frame):
        """
        Handles the NACK command: Unacknowledges receipt of a message.
        For now, this is just a placeholder to implement this version of the protocol
        """
        if not frame.headers.get('message-id'):
            raise ProtocolError("No message-id specified for NACK command.")
        if not frame.headers.get('subscription'):
            raise ProtocolError("No subscription specified for NACK command.")

    def _negotiate_protocol(self, frame, response):
        client_versions = frame.headers.get('accept-version')
        if not client_versions:
            raise ProtocolError('No version specified')
        common = set(client_versions.split(',')) & self.SUPPORTED_VERSIONS
        if not common:
            versions = ','.join(self.SUPPORTED_VERSIONS)
            self.engine.connection.send_frame(
                Frame(frames.ERROR,
                      headers={
                          'version': versions,
                          'content-type': frames.TEXT_PLAIN
                      },
                      body='Supported protocol versions are {0}'.format(
                          versions)))
        else:
            response.headers['version'] = max(common)
            protocol_class = PROTOCOL_MAP[response.headers['version']]
            if type(self) is not protocol_class:
                self.engine.protocol = protocol_class(self.engine)
                self.engine.protocol.connect(frame, response=response)