Esempio n. 1
0
    def process_frame(self, frame):
        """
        Dispatches a received frame to the appropriate internal method.
        
        @param frame: The frame that was received.
        @type frame: L{coilmq.frame.StompFrame} 
        """
        cmd_method = frame.cmd.lower()

        if not cmd_method in VALID_COMMANDS:
            raise ProtocolError("Invalid STOMP command: %s" % frame.cmd)

        method = getattr(self, cmd_method, None)

        if not self.connected and method != self.connect:
            raise ProtocolError("Not connected.")

        try:
            transaction = frame.headers.get('transaction')
            if not transaction or method in (self.begin, self.commit,
                                             self.abort):
                method(frame)
            else:
                if not transaction in self.transactions:
                    raise ProtocolError("Invalid transaction specified: %s" %
                                        transaction)
                self.transactions[transaction].append(frame)
        except Exception, e:
            self.log.error("Error processing STOMP frame: %s" % e)
            self.log.exception(e)
            try:
                self.connection.send_frame(ErrorFrame(str(e), str(e)))
            except Exception, e:
                self.log.error("Could not send error frame: %s" % e)
                self.log.exception(e)
Esempio n. 2
0
 def connect(self, frame, response=None):
     host = frame.headers.get('host')
     if not host:
         raise ProtocolError('"host" header is required')
     if host != socket.getfqdn():
         raise ProtocolError(
             'Virtual hosting is not supported or host is unknown')
     super(STOMP12, self).connect(frame, response)
Esempio n. 3
0
 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.")
Esempio n. 4
0
 def abort(self, frame):
     """
     Handles ABORT command: Rolls back specified transaction.
     """
     if not frame.transaction:
         raise ProtocolError("Missing transaction for ABORT command.")
     
     if not frame.transaction in self.transactions:
         raise ProtocolError("Invalid transaction: %s" % frame.transaction)
     
     self.queue_manager.resend_transaction_frames(self.connection, frame.transaction)
     del self.transactions[frame.transaction]
Esempio n. 5
0
 def ack(self, frame):
     """
     Handles the ACK command: Acknowledges receipt of a message.
     """
     if not frame.message_id:
         raise ProtocolError("No message-id specified for ACK command.")
     self.queue_manager.ack(self.connection, frame)
Esempio n. 6
0
 def commit(self, frame):
     """
     Handles COMMIT command: Commits specified transaction.
     """
     if not frame.transaction:
         raise ProtocolError("Missing transaction for COMMIT command.")
     
     if not frame.transaction in self.transactions:
         raise ProtocolError("Invalid transaction: %s" % frame.transaction)
     
     for tframe in self.transactions[frame.transaction]:
         del tframe.headers['transaction']
         self.process_frame(tframe)
     
     self.queue_manager.clear_transaction_frames(self.connection, frame.transaction)
     del self.transactions[frame.transaction]
Esempio n. 7
0
    def begin(self, frame):
        """
        Handles BEGING command: Starts a new transaction.
        """
        if not frame.transaction:
            raise ProtocolError("Missing transaction for BEGIN command.")

        self.transactions[frame.transaction] = []
Esempio n. 8
0
    def process_frame(self, frame):
        """
        Dispatches a received frame to the appropriate internal method.

        @param frame: The frame that was received.
        @type frame: C{stompclient.frame.Frame}
        """
        cmd_method = frame.cmd.lower()

        if not cmd_method in VALID_COMMANDS:
            raise ProtocolError("Invalid STOMP command: {}".format(frame.cmd))

        method = getattr(self, cmd_method, None)

        if not self.engine.connected and method not in (self.connect,
                                                        self.stomp):
            raise ProtocolError("Not connected.")

        try:
            transaction = frame.headers.get('transaction')
            if not transaction or method in (self.begin, self.commit,
                                             self.abort):
                method(frame)
            else:
                if not transaction in self.engine.transactions:
                    raise ProtocolError("Invalid transaction specified: %s" %
                                        transaction)
                self.engine.transactions[transaction].append(frame)
        except Exception as e:
            self.engine.log.error("Error processing STOMP frame: %s" % e)
            self.engine.log.exception(e)
            try:
                self.engine.connection.send_frame(ErrorFrame(str(e), str(e)))
            except Exception as e:  # pragma: no cover
                self.engine.log.error("Could not send error frame: %s" % e)
                self.engine.log.exception(e)
        else:
            # The protocol is not especially clear here (not sure why I'm surprised)
            # about the expected behavior WRT receipts and errors.  We will assume that
            # the RECEIPT frame should not be sent if there is an error frame.
            # Also we'll assume that a transaction should not preclude sending the receipt
            # frame.
            # import pdb; pdb.set_trace()
            if frame.headers.get('receipt') and method != self.connect:
                self.engine.connection.send_frame(
                    ReceiptFrame(receipt=frame.headers.get('receipt')))
Esempio n. 9
0
    def unsubscribe(self, frame):
        """
        Handle the UNSUBSCRIBE command: Removes this connection from destination.
        """
        dest = frame.headers.get('destination')
        if not dest:
            raise ProtocolError('Missing destination for UNSUBSCRIBE command.')

        if dest.startswith('/queue/'):
            self.queue_manager.unsubscribe(self.connection, dest)
        else:
            self.topic_manager.unsubscribe(self.connection, dest)
Esempio n. 10
0
    def send(self, frame):
        """
        Handle the SEND command: Delivers a message to a queue or topic (default).
        """
        dest = frame.headers.get('destination')
        if not dest:
            raise ProtocolError('Missing destination for SEND command.')

        if dest.startswith('/queue/'):
            self.queue_manager.send(frame)
        else:
            self.topic_manager.send(frame)
Esempio n. 11
0
    def subscribe(self, frame):
        """
        Handle the SUBSCRIBE command: Adds this connection to destination.
        """
        ack = frame.headers.get('ack')
        reliable = ack and ack.lower() == 'client'

        self.connection.reliable_subscriber = reliable

        dest = frame.headers.get('destination')
        if not dest:
            raise ProtocolError('Missing destination for SUBSCRIBE command.')

        if dest.startswith('/queue/'):
            self.queue_manager.subscribe(self.connection, dest)
        else:
            self.topic_manager.subscribe(self.connection, dest)
Esempio n. 12
0
 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)