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{stompclient.util.FrameBuffer} @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): if self.server.timeout is not None: self.request.settimeout(self.server.timeout) self.debug = False self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__)) self.buffer = FrameBuffer() 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 not self.server._shutdown_request_event.is_set(): try: 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) if not self.engine.connected: raise ClientDisconnected() except socket.timeout: pass except ClientDisconnected: self.log.debug("Client disconnected, discontinuing read loop.") except Exception, e: self.log.error("Error receiving data (unbinding): %s" % e) self.engine.unbind() raise
def setup(self): if self.server.timeout is not None: self.request.settimeout(self.server.timeout) self.debug = False self.log = logging.getLogger('%s.%s' % (self.__module__, self.__class__.__name__)) self.buffer = FrameBuffer() self.engine = StompEngine(connection=self, authenticator=self.server.authenticator, queue_manager=self.server.queue_manager, topic_manager=self.server.topic_manager)
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 = FrameBuffer() if connect: self._connect()
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 Frame instances that have been received. @type received_frames: C{Queue.Queue} containing any received C{stompclient.frame.Frame} """ 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 = FrameBuffer() if connect: self._connect() def connect(self, headers=None): if headers is None: headers = {} self.send_frame(Frame('CONNECT', headers=headers)) def send(self, destination, message, set_content_length=True, extra_headers=None): if extra_headers is None: extra_headers = {} headers = extra_headers headers['destination'] = destination if set_content_length: headers['content-length'] = len(message) self.send_frame(Frame('SEND', headers=headers, body=message)) def subscribe(self, destination): self.send_frame(Frame('SUBSCRIBE', headers={'destination': destination})) def send_frame(self, frame): """ Sends a stomp frame. @param frame: The stomp frame to send. @type frame: L{stompclient.frame.Frame} """ 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(Frame('DISCONNECT')) self.sock.close(); def close(self): if not self.connected: raise RuntimeError("Not connected") self.connected = False self.read_stopped.wait() self.sock.close()