docs: 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')))