Just for learn

This commit is contained in:
Sheng 2017-02-08 13:52:49 +08:00
parent 938bba32a4
commit cee1b0be33
19 changed files with 3444 additions and 1 deletions

111
eventloop.py Normal file
View file

@ -0,0 +1,111 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, \
with_statement
import logging
import time
import traceback
import errno
from shadowsocks import selectors
from shadowsocks.selectors import (EVENT_READ, EVENT_WRITE, EVENT_ERROR,
errno_from_exception)
POLL_IN = EVENT_READ
POLL_OUT = EVENT_WRITE
POLL_ERR = EVENT_ERROR
TIMEOUT_PRECISION = 10
class EventLoop:
def __init__(self):
self._selector = selectors.DefaultSelector()
self._stopping = False
self._last_time = time.time()
self._periodic_callbacks = []
def poll(self, timeout=None):
return self._selector.select(timeout)
def add(self, sock, events, data):
events |= selectors.EVENT_ERROR
return self._selector.register(sock, events, data)
def remove(self, sock):
try:
return self._selector.unregister(sock)
except KeyError:
pass
def modify(self, sock, events, data):
events |= selectors.EVENT_ERROR
try:
key = self._selector.modify(sock, events, data)
except KeyError:
key = self.add(sock, events, data)
return key
def add_periodic(self, callback):
self._periodic_callbacks.append(callback)
def remove_periodic(self, callback):
self._periodic_callbacks.remove(callback)
def fd_count(self):
return len(self._selector.get_map())
def run(self):
logging.debug('Starting event loop')
while not self._stopping:
asap = False
try:
events = self.poll(timeout=TIMEOUT_PRECISION)
except (OSError, IOError) as e:
if errno_from_exception(e) in (errno.EPIPE, errno.EINTR):
# EPIPE: Happens when the client closes the connection
# EINTR: Happens when received a signal
# handles them as soon as possible
asap = True
logging.debug('poll: %s', e)
else:
logging.error('poll: %s', e)
traceback.print_exc()
continue
for key, event in events:
if type(key.data) == tuple:
handler = key.data[0]
args = key.data[1:]
else:
handler = key.data
args = ()
sock = key.fileobj
if hasattr(handler, 'handle_event'):
handler = handler.handle_event
try:
handler(sock, event, *args)
except Exception as e:
logging.debug(e)
traceback.print_exc()
raise
now = time.time()
if asap or now - self._last_time >= TIMEOUT_PRECISION:
for callback in self._periodic_callbacks:
callback()
self._last_time = now
logging.debug('Got {} fds registered'.format(self.fd_count()))
logging.debug('Stopping event loop')
self._selector.close()
def stop(self):
self._stopping = True