Mercurial > cosocket
view taw.py @ 1:f1159b9ec823
Initial implementation of coroutine-based server.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Fri, 17 Apr 2009 15:18:19 -0700 |
parents | fb5e84a8eb8a |
children | f6f9cc0385be |
line wrap: on
line source
import time import socket import asyncore import asynchat class ChattyCoroutineServer(asyncore.dispatcher): def __init__(self, addr, coroutineFactory): asyncore.dispatcher.__init__(self) self.__coroutineFactory = coroutineFactory self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(addr) self.listen(1) def run(self): while 1: asyncore.loop(timeout = 0.5) def handle_accept(self): conn, addr = self.accept() AsyncChatCoroutineBridge(conn, addr, self.__coroutineFactory()) class AsyncChatCoroutineBridge(asynchat.async_chat): def __init__(self, conn, addr, coroutine): asynchat.async_chat.__init__(self, conn) self.set_terminator(None) self.__coroutine = coroutine(addr) self.__data = [] self.__process_next_instruction() def __process_next_instruction(self, feedback = None): try: instruction = self.__coroutine.send(feedback) except StopIteration: instruction = {'op': 'close'} if instruction['op'] == 'receive': if instruction['terminator']: self.set_terminator(instruction['terminator']) elif instruction['length']: self.set_terminator(instruction['length']) else: raise ValueError(instruction) elif instruction['op'] == 'send': self.push(instruction['content']) elif instruction['op'] == 'close': self.close() def initiate_send(self): asynchat.async_chat.initiate_send(self) if ((not self.ac_out_buffer) and (len(self.producer_fifo) == 0) and self.connected): self.__process_next_instruction() def collect_incoming_data(self, data): # TODO: Enforce some maximum data length. self.__data.append(data) def found_terminator(self): self.set_terminator(None) data = ''.join(self.__data) self.__process_next_instruction(data) class ChattyCoroutine(object): def receive(self, terminator = None, length = None): return {'op': 'receive', 'terminator': terminator, 'length': length} def send(self, content): return {'op': 'send', 'content': content} class LameHttpCoroutine(ChattyCoroutine): def __call__(self, addr): req = yield self.receive(terminator = '\r\n\r\n') msg = 'hello %s.' % addr[0] yield self.send('HTTP/1.1 200 OK\r\n' + 'Content-Length: %d\r\n' % len(msg) + 'Content-Type: text/plain\r\n\r\n' + msg) if __name__ == '__main__': server = ChattyCoroutineServer(('127.0.0.1', 8071), LameHttpCoroutine) server.run()