Esempio n. 1
0
 def test_extract_message_multi(self):
     """ Test the handling of multiple concatenated messages by the buffer. """
     
     m1 = 'CONNECT\nsession:207567f3-cce7-4a0a-930b-46fc394dd53d\n\n0123456789\x00\n'
     m2 = 'SUBSCRIBE\nack:auto\ndestination:/queue/test\n\n\x00SEND\ndestination:/queue/test\n\n\x00'
     
     sb = StompFrameBuffer()
     sb.append(m1)
     f1 = sb.extract_message()
     assert f1.cmd == 'CONNECT'
     assert f1.body == '0123456789'
     
     assert sb.extract_message() is None
     
     sb.append(m2)
     f2 = sb.extract_message()
     f3 = sb.extract_message()
     
     assert f2.cmd == 'SUBSCRIBE'
     assert f2.body == ''
     assert f3.cmd == 'SEND'
     assert f3.destination == '/queue/test'
     assert f3.body == ''
     
     assert sb.extract_message() is None
Esempio n. 2
0
 def test_extract_message(self):
     """ Test extracting a single frame. """
     sb = StompFrameBuffer()
     m1 = self.createMessage('connect', {'session': uuid.uuid4()}, 'This is the body')
     sb.append(m1)
     msg = sb.extract_message()
     assert isinstance(msg, stomper.Frame)
     assert m1 == msg.pack()
Esempio n. 3
0
 def setup(self):
     self.debug = False
     self.log = logging.getLogger(
         '%s.%s' % (self.__module__, self.__class__.__name__))
     self.buffer = StompFrameBuffer()
     self.engine = StompEngine(connection=self,
                               authenticator=self.server.authenticator,
                               queue_manager=self.server.queue_manager,
                               topic_manager=self.server.topic_manager)
Esempio n. 4
0
class StompProtocol(Protocol, StompConnection):
    """
    Subclass of C{twisted.internet.protocol.Protocol} for handling STOMP communications.
    
    An instance of this class will be created for each connecting client. 
    
    @ivar buffer: A StompBuffer instance which buffers received data (to ensure we deal with
                    complete STOMP messages.
    @type buffer: C{stomper.stompbuffer.StompBuffer}
    
    @ivar engine: The STOMP protocol engine.
    @type engine: L{coilmq.engine.StompEngine}
    """
    def __init__(self, queue_manager, topic_manager):
        self.log = logging.getLogger(
            '%s.%s' % (self.__class__.__module__, self.__class__.__name__))
        self.log.debug("Initializing StompProtocol.")
        self.buffer = StompFrameBuffer()
        self.engine = StompEngine(
            connection=self,
            authenticator=None,  # FIXME: Add the authenticator
            queue_manager=queue_manager,
            topic_manager=topic_manager)

    def connectionLost(self, reason):
        Protocol.connectionLost(self, reason)
        self.log.debug("Connection lost.")
        self.engine.unbind()

    def connectionMade(self):
        self.log.debug("Connection made.")

    def dataReceived(self, data):
        """ Twisted calls this method when data is received.
         
        Note: The data may not be not be a complete frame or may be more than
        one frame.
        """
        self.log.debug("Data received: %s" % data)
        self.buffer.append(data)

        # print '%r' % self.buffer

        for frame in self.buffer:
            self.log.debug("Processing frame: %s" % frame)
            self.engine.process_frame(frame)

    def send_frame(self, frame):
        """ Sends a frame to connected socket client.
        
        (Sorry, Twisted, our code is PEP-8.)
        
        @param frame: The frame to send.
        @type frame: L{coilmq.frame.StompFrame}
        """
        self.transport.write(frame.pack())
Esempio n. 5
0
 def __init__(self, queue_manager, topic_manager):
     self.log = logging.getLogger(
         '%s.%s' % (self.__class__.__module__, self.__class__.__name__))
     self.log.debug("Initializing StompProtocol.")
     self.buffer = StompFrameBuffer()
     self.engine = StompEngine(
         connection=self,
         authenticator=None,  # FIXME: Add the authenticator
         queue_manager=queue_manager,
         topic_manager=topic_manager)
Esempio n. 6
0
class StompProtocol(Protocol, StompConnection):
    """
    Subclass of C{twisted.internet.protocol.Protocol} for handling STOMP communications.
    
    An instance of this class will be created for each connecting client. 
    
    @ivar buffer: A StompBuffer instance which buffers received data (to ensure we deal with
                    complete STOMP messages.
    @type buffer: C{stomper.stompbuffer.StompBuffer}
    
    @ivar engine: The STOMP protocol engine.
    @type engine: L{coilmq.engine.StompEngine}
    """
    def __init__(self, queue_manager, topic_manager):
        self.log = logging.getLogger('%s.%s' % (self.__class__.__module__, self.__class__.__name__))
        self.log.debug("Initializing StompProtocol.")
        self.buffer = StompFrameBuffer()
        self.engine = StompEngine(connection=self,
                                  authenticator=None, # FIXME: Add the authenticator
                                  queue_manager=queue_manager,
                                  topic_manager=topic_manager) 

    def connectionLost(self, reason):
        Protocol.connectionLost(self, reason)
        self.log.debug("Connection lost.")
        self.engine.unbind()

    def connectionMade(self):
        self.log.debug("Connection made.")

    def dataReceived(self, data):
        """ Twisted calls this method when data is received.
         
        Note: The data may not be not be a complete frame or may be more than
        one frame.
        """
        self.log.debug("Data received: %s" % data)
        self.buffer.append(data)
        
        # print '%r' % self.buffer
        
        for frame in self.buffer:
            self.log.debug("Processing frame: %s" % frame)
            self.engine.process_frame(frame)
    
    def send_frame(self, frame):
        """ Sends a frame to connected socket client.
        
        (Sorry, Twisted, our code is PEP-8.)
        
        @param frame: The frame to send.
        @type frame: L{coilmq.frame.StompFrame}
        """
        self.transport.write(frame.pack())
class StompRequestHandler(BaseRequestHandler, StompConnection):
    """
    Class that will be instantiated to handle STOMP connections.

    This class will be instantiated once per connection to the server.  In a multi-threaded
    context, that means that instances of this class are scoped to a single thread.  It should
    be noted that while the L{coilmq.engine.StompEngine} instance will be thread-local, the 
    storage containers configured into the engine are not thread-local (and hence must be
    thread-safe). 
    
    @ivar buffer: A StompBuffer instance which buffers received data (to ensure we deal with
                    complete STOMP messages.
    @type buffer: C{stomper.stompbuffer.StompBuffer}
    
    @ivar engine: The STOMP protocol engine.
    @type engine: L{coilmq.engine.StompEngine}
    
    @ivar debug: Whether to enable extra-verbose debug logging.  (Will be logged at debug level.)
    @type debug: C{bool}
    """
    
    def setup(self):
        self.debug = False
        self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__))
        self.buffer = StompFrameBuffer()
        self.engine = StompEngine(connection=self,
                                  authenticator=self.server.authenticator,
                                  queue_manager=self.server.queue_manager,
                                  topic_manager=self.server.topic_manager)
        
    def handle(self):
        """
        Handle a new socket connection.
        """
        # self.request is the TCP socket connected to the client
        try:
            while True:
                data = self.request.recv(8192)
                if not data:
                    break
                if self.debug:
                    self.log.debug("RECV: %r" % data)
                self.buffer.append(data)
                
                for frame in self.buffer:
                    self.log.debug("Processing frame: %s" % frame)
                    self.engine.process_frame(frame)
        except Exception, e:
            self.log.error("Error receiving data (unbinding): %s" % e)
            self.engine.unbind()
            raise
Esempio n. 8
0
class StompRequestHandler(BaseRequestHandler, StompConnection):
    """
    Class that will be instantiated to handle STOMP connections.

    This class will be instantiated once per connection to the server.  In a multi-threaded
    context, that means that instances of this class are scoped to a single thread.  It should
    be noted that while the L{coilmq.engine.StompEngine} instance will be thread-local, the 
    storage containers configured into the engine are not thread-local (and hence must be
    thread-safe). 
    
    @ivar buffer: A StompBuffer instance which buffers received data (to ensure we deal with
                    complete STOMP messages.
    @type buffer: C{stomper.stompbuffer.StompBuffer}
    
    @ivar engine: The STOMP protocol engine.
    @type engine: L{coilmq.engine.StompEngine}
    
    @ivar debug: Whether to enable extra-verbose debug logging.  (Will be logged at debug level.)
    @type debug: C{bool}
    """
    def setup(self):
        self.debug = False
        self.log = logging.getLogger(
            '%s.%s' % (self.__module__, self.__class__.__name__))
        self.buffer = StompFrameBuffer()
        self.engine = StompEngine(connection=self,
                                  authenticator=self.server.authenticator,
                                  queue_manager=self.server.queue_manager,
                                  topic_manager=self.server.topic_manager)

    def handle(self):
        """
        Handle a new socket connection.
        """
        # self.request is the TCP socket connected to the client
        try:
            while True:
                data = self.request.recv(8192)
                if not data:
                    break
                if self.debug:
                    self.log.debug("RECV: %r" % data)
                self.buffer.append(data)

                for frame in self.buffer:
                    self.log.debug("Processing frame: %s" % frame)
                    self.engine.process_frame(frame)
        except Exception, e:
            self.log.error("Error receiving data (unbinding): %s" % e)
            self.engine.unbind()
            raise
Esempio n. 9
0
 def __init__(self, addr, connect=True):
     """
     @param addr: The (host,port) tuple for connection.
     @type addr: C{tuple}
     
     @param connect: Whether to connect socket to specified addr.
     @type connect: C{bool}
     """
     self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__))
     self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     self.addr = addr
     self.received_frames = Queue()
     self.read_stopped = threading.Event()
     self.buffer = StompFrameBuffer()
     if connect:
         self._connect()
 def setup(self):
     self.debug = False
     self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__))
     self.buffer = StompFrameBuffer()
     self.engine = StompEngine(connection=self,
                               authenticator=self.server.authenticator,
                               queue_manager=self.server.queue_manager,
                               topic_manager=self.server.topic_manager)
Esempio n. 11
0
 def __init__(self, queue_manager, topic_manager):
     self.log = logging.getLogger('%s.%s' % (self.__class__.__module__, self.__class__.__name__))
     self.log.debug("Initializing StompProtocol.")
     self.buffer = StompFrameBuffer()
     self.engine = StompEngine(connection=self,
                               authenticator=None, # FIXME: Add the authenticator
                               queue_manager=queue_manager,
                               topic_manager=topic_manager) 
Esempio n. 12
0
 def test_iteration(self):
     """ Test the iteration feature of our buffer."""
     sb = StompFrameBuffer()
     m1 = self.createMessage('connect', {'session': uuid.uuid4()}, 'This is the body')
     m2 = self.createMessage('send', {'destination': '/queue/sample'}, 'This is the body-2')
     print '%r' % m1
     print '%r' % m2
     sb.append(m1)
     sb.append(m2)
     
     assert sb is iter(sb)
     
     idx = 0
     expected = (m1, m2)
     for frame in sb:
         assert isinstance(frame, stomper.Frame)
         assert expected[idx] == frame.pack()
         idx += 1
     
     assert idx == 2
Esempio n. 13
0
 def test_extract_message_binary(self):
     """ Test extracting a binary frame. """
     sb = StompFrameBuffer()
     binmsg = "\x00\x00HELLO\x00\x00DONKEY\x00\x00"
     m1 = self.createMessage('send', {'content-length': len(binmsg)}, binmsg)
     sb.append(m1)
     msg = sb.extract_message()
     assert isinstance(msg, stomper.Frame)
     assert msg.pack() == m1
  
     m2 = self.createMessage('send', {'content-length': len(binmsg), 'x-other-header': 'value'}, binmsg)
     sb.append(m2)
     msg = sb.extract_message()
     assert isinstance(msg, stomper.Frame)
     assert msg.pack() == m2
Esempio n. 14
0
 def test_extract_message_fragmented(self):
     """ Test the handling of fragmented frame data. """
     
     m1_1  = 'CONNECT\nsession:207567f3-cce7-4a0a-930b-'
     m1_2 = '46fc394dd53d\n\n0123456789\x00\nSUBSCRIBE\nack:a'
     
     m1_3 = 'uto\ndestination:/queue/test\n\n\x00SE'
     m1_4 = 'ND\ndestination:/queue/test\n\n0123456789\x00'
     
     sb = StompFrameBuffer()
     sb.append(m1_1)
     
     assert sb.extract_message() is None
     
     sb.append(m1_2)
     
     f1 = sb.extract_message()
     assert f1.cmd == 'CONNECT'
     assert f1.body == '0123456789'
     assert sb.extract_message() is None
     
     sb.append(m1_3)
     f2 = sb.extract_message()
     assert f2.cmd == 'SUBSCRIBE'        
     assert sb.extract_message() is None
     
     sb.append(m1_4)
     f3 = sb.extract_message()
     assert f3.cmd == 'SEND'
     assert f3.destination == '/queue/test'
     assert f3.body == '0123456789'
Esempio n. 15
0
class TestStompClient(object):
    """
    A stomp client for use in testing.
    
    This client spawns a listener thread and pushes anything that comes in onto the 
    read_frames queue.
    
    @ivar received_frames: A queue of StompFrame instances that have been received.
    @type received_frames: C{Queue.Queue} containing any received L{coilmq.frame.StompFrame}
    """
    def __init__(self, addr, connect=True):
        """
        @param addr: The (host,port) tuple for connection.
        @type addr: C{tuple}
        
        @param connect: Whether to connect socket to specified addr.
        @type connect: C{bool}
        """
        self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__))
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.addr = addr
        self.received_frames = Queue()
        self.read_stopped = threading.Event()
        self.buffer = StompFrameBuffer()
        if connect:
            self._connect()
    
    def connect(self, headers=None):
        if headers is None:
            headers = {}
        self.send_frame(StompFrame('CONNECT', headers=headers))
        
    def send(self, destination, message, set_content_length=True):
        headers = {'destination': destination}
        if set_content_length: headers['content-length'] = len(message)
        self.send_frame(StompFrame('SEND', headers=headers, body=message))
    
    def subscribe(self, destination):
        self.send_frame(StompFrame('SUBSCRIBE', headers={'destination': destination}))
        
    def send_frame(self, frame):
        """
        Sends a stomp frame.
        @param frame: The stomp frame to send.
        @type frame: L{coilmq.frame.StompFrame}
        """
        if not self.connected:
            raise RuntimeError("Not connected")
        self.sock.send(frame.pack())
    
    def _connect(self):
        self.sock.connect(self.addr)
        self.connected = True
        self.read_stopped.clear()
        t = threading.Thread(target=self._read_loop, name="client-receiver-%s" % hex(id(self)))
        t.start()
    
    def _read_loop(self):
        while self.connected:
            r, w, e = select.select([self.sock], [], [], 0.1)
            if r:
                data = self.sock.recv(1024)
                self.log.debug("Data received: %r" % data)
                self.buffer.append(data)
                for frame in self.buffer:
                    self.log.debug("Processing frame: %s" % frame)
                    self.received_frames.put(frame)
        self.read_stopped.set()
        # print "Read loop has been quit! for %s" % id(self)
    
    def disconnect(self):
        self.send_frame(StompFrame('DISCONNECT'))
        
    def close(self):
        if not self.connected:
            raise RuntimeError("Not connected")
        self.connected = False
        self.read_stopped.wait()
        self.sock.close()