import os
import signal
import socket
import sys
from errno import EAGAIN, EWOULDBLOCK
import pyev
# ------------------------------------------------------------------------------
# some konstants
# ------------------------------------------------------------------------------
RETRY_STATES = tuple(set([EAGAIN, EWOULDBLOCK])) # EINTR
HELLO_WORLD = '\r\n'.join([
'HTTP/1.1 200 OK', 'Connection: close', 'Content-type: text/html',
'Server: MicroHTTPServer/0.1', 'Content-Length: 11', '', 'Hello World'
])
class HTTPConnection(object):
def __init__(self, connection, address, server):
self.connection = connection
self.address = address
self.server = server
self._buffer = ''
connection.setblocking(0)
self._event = pyev.Io(self.connection.fileno(), pyev.EV_READ, LOOP, self.do_read)
self._event.start()
def do_read(self, watcher, events):
print "Reading"
self._buffer += self.connection.recv(1024)
if '\r\n\r\n' in self._buffer:
self._event.stop()
self.hello()
def hello(self):
wfile = self.connection.makefile('wb', 0)
wfile.write(HELLO_WORLD)
wfile.flush()
wfile.close()
self.connection.close()
# ------------------------------------------------------------------------------
# our kore server
# ------------------------------------------------------------------------------
class MicroHTTPServer(object):
"""Micro HTTP Server."""
_socket = None
_shutdown = False
def __init__(self, handler=HTTPConnection):
self.handler = handler
def listen(self, host='', port=9090, backlog=1024):
"""Start listening on the given ``host`` and ``port``."""
assert not self._socket, "This server is already listening."
self.host, self.port = host, port
self._socket = sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
if sys.platform == 'darwin':
backlog = min(backlog, 128)
elif os.name == 'nt':
backlog = min(backlog, 5)
sock.listen(backlog)
socket_descriptor = sock.fileno()
self.register(socket_descriptor)
# flags = fcntl.fcntl(self._socket.fileno(), fcntl.F_GETFD)
# flags |= fcntl.FD_CLOEXEC
# fcntl.fcntl(self._socket.fileno(), fcntl.F_SETFD, flags)
def register(self, socket_descriptor):
ev = pyev.Io(socket_descriptor, pyev.EV_READ, LOOP, self.handle_connection)
print ev.start()
print "Started server"
def handle_connection(self, watcher, events):
try:
connection, address = self._socket.accept()
except socket.error, reason:
if reason[0] in RETRY_STATES:
return
raise
self.handler(connection, address, self)
if 1:
LOOP = pyev.default_loop()
# LOOP = pyev.Loop(pyev.EVBACKEND_SELECT)
elif 'linux' in sys.platform:
LOOP = pyev.Loop(pyev.EVBACKEND_EPOLL)
elif sys.platform == 'darwin':
LOOP = pyev.Loop(pyev.EVBACKEND_KQUEUE)
def sig_cb(watcher, events):
print("got SIGINT")
# optional - stop all watchers
if watcher.data:
print("stopping watchers: {0}".format(watcher.data))
for w in watcher.data:
w.stop()
# unloop all nested loop
print("stopping the loop: {0}".format(watcher.loop))
watcher.loop.unloop()
sig = pyev.Signal(signal.SIGINT, LOOP, sig_cb)
sig.start()
def start():
s = MicroHTTPServer()
s.listen()
LOOP.loop()
# ------------------------------------------------------------------------------
# test
# ------------------------------------------------------------------------------
start()