114 lines
3.0 KiB
Python
114 lines
3.0 KiB
Python
from py.__.green import greensock2
|
|
import socket, errno, os
|
|
|
|
error = socket.error
|
|
|
|
|
|
class _delegate(object):
|
|
def __init__(self, methname):
|
|
self.methname = methname
|
|
def __get__(self, obj, typ=None):
|
|
result = getattr(obj._s, self.methname)
|
|
setattr(obj, self.methname, result)
|
|
return result
|
|
|
|
|
|
class GreenSocket(object):
|
|
|
|
def __init__(self, family = socket.AF_INET,
|
|
type = socket.SOCK_STREAM,
|
|
proto = 0):
|
|
self._s = socket.socket(family, type, proto)
|
|
self._s.setblocking(False)
|
|
|
|
def fromsocket(cls, s):
|
|
if isinstance(s, GreenSocket):
|
|
s = s._s
|
|
result = GreenSocket.__new__(cls)
|
|
result._s = s
|
|
s.setblocking(False)
|
|
return result
|
|
fromsocket = classmethod(fromsocket)
|
|
|
|
def accept(self):
|
|
while 1:
|
|
try:
|
|
s, addr = self._s.accept()
|
|
break
|
|
except error, e:
|
|
if e.args[0] not in (errno.EAGAIN, errno.EWOULDBLOCK):
|
|
raise
|
|
self.wait_input()
|
|
return self.fromsocket(s), addr
|
|
|
|
bind = _delegate("bind")
|
|
close = _delegate("close")
|
|
|
|
def connect(self, addr):
|
|
err = self.connect_ex(addr)
|
|
if err:
|
|
raise error(err, os.strerror(err))
|
|
|
|
def connect_ex(self, addr):
|
|
err = self._s.connect_ex(addr)
|
|
if err == errno.EINPROGRESS:
|
|
greensock2.wait_output(self._s)
|
|
err = self._s.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
|
|
return err
|
|
|
|
#XXX dup
|
|
fileno = _delegate("fileno")
|
|
getpeername = _delegate("getpeername")
|
|
getsockname = _delegate("getsockname")
|
|
getsockopt = _delegate("getsockopt")
|
|
listen = _delegate("listen")
|
|
|
|
def makefile(self, mode='r', bufsize=-1):
|
|
# hack, but reusing the internal socket._fileobject should just work
|
|
return socket._fileobject(self, mode, bufsize)
|
|
|
|
def recv(self, bufsize):
|
|
return greensock2.recv(self._s, bufsize)
|
|
|
|
def recvall(self, bufsize):
|
|
return greensock2.recvall(self._s, bufsize)
|
|
|
|
def recvfrom(self, bufsize):
|
|
self.wait_input()
|
|
buf, addr = self._s.recvfrom(bufsize)
|
|
if not buf:
|
|
raise ConnexionClosed("inbound connexion closed")
|
|
return buf, addr
|
|
|
|
def send(self, data):
|
|
self.wait_output()
|
|
return self._s.send(data)
|
|
|
|
def sendto(self, data, addr):
|
|
self.wait_output()
|
|
return self._s.sendto(data, addr)
|
|
|
|
def sendall(self, data):
|
|
greensock2.sendall(self._s, data)
|
|
|
|
setsockopt = _delegate("setsockopt")
|
|
shutdown = _delegate("shutdown")
|
|
|
|
def shutdown_rd(self):
|
|
try:
|
|
self._s.shutdown(socket.SHUT_RD)
|
|
except error:
|
|
pass
|
|
|
|
def shutdown_wr(self):
|
|
try:
|
|
self._s.shutdown(socket.SHUT_WR)
|
|
except error:
|
|
pass
|
|
|
|
def wait_input(self):
|
|
greensock2.wait_input(self._s)
|
|
|
|
def wait_output(self):
|
|
greensock2.wait_output(self._s)
|