コード例 #1
0
ファイル: clients.py プロジェクト: noirbee/splicy
class InboundClient(object):

    IO_TIMEOUT = 10
    MAX_REQUEST_SIZE = 4096

    def __init__(self, server, loop, sock, address_info):
        self.server = server
        self.loop = loop
        self.sock = sock
        self.sock.setblocking(0)
        self.address_info = address_info
        self.pipe_buffer = PipeBuffer()
        self.watchers = {
            'recv': loop.io(sock.fileno(), EV_READ, self.recv_data),
            'send': loop.io(sock.fileno(), EV_WRITE, self.send_data, 0),
            'timeout': loop.timer(self.IO_TIMEOUT, self.IO_TIMEOUT,
                                  self.timeout),
            }
        self.http_parser = HTTPParser()

    def start(self):
        self.watchers['recv'].start()
        self.watchers['timeout'].start()
        # send is not started yet

    def stop(self):
        for watcher in self.watchers.values():
            watcher.stop()
        self.sock.close()
        self.pipe_buffer.close()
        self.server.remove_client(self)
        self.server.logger.debug('Stopped client: %s', self)

    def recv_data(self, watcher, revents):
        try:
            data = self.sock.recv(self.MAX_REQUEST_SIZE, socket.MSG_PEEK)
            self.http_parser.execute(data)
            if self.http_parser.has_error():
                self.stop()
            elif self.http_parser.is_finished():
                # IO_TIMEOUT seconds at most for the response to come in
                self.watchers['timeout'].reset()
                data = self.sock.recv(self.MAX_REQUEST_SIZE)
                # We're not interested in any more data from this peer
                self.sock.shutdown(socket.SHUT_RD)
                watcher.stop()
                # Ask our server for the response, cached or not
                self.server.proxy(self, self.http_parser, data)
        except:
            self.server.logger.exception('While recv_data():')
            raise

    def start_sending(self):
        self.watchers['send'].start()

    def send_data(self, watcher, revents):
        self.watchers['timeout'].reset()
        self.server.logger.debug('Sending (%d - %d) = %d bytes to %s',
                                 self.pipe_buffer.size, watcher.data,
                                 self.pipe_buffer.size - watcher.data, self)
        watcher.data += splice(self.pipe_buffer.reader, None,
                               self.sock.fileno(), None,
                               self.pipe_buffer.size - watcher.data)[0]
        if watcher.data >= self.pipe_buffer.size:
            self.server.logger.debug('Done sending data to %s', self)
            self.stop()
        self.server.logger.debug('Sent %d bytes to %s', watcher.data, self)

    def timeout(self, watcher, revents):
        self.stop()