Fixed bug in select
This commit is contained in:
@ -67,71 +67,99 @@ def poll():
|
|||||||
"""
|
"""
|
||||||
return Poll()
|
return Poll()
|
||||||
|
|
||||||
|
def _has_data(S):
|
||||||
|
"""True if the given I2P socket has data waiting."""
|
||||||
|
try:
|
||||||
|
S.recv(1, i2p.socket.MSG_PEEK | i2p.socket.MSG_DONTWAIT)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _noblock_select(readlist, writelist, errlist):
|
||||||
|
"""Makes a single query of the given sockets, like
|
||||||
|
select() with timeout 0.0."""
|
||||||
|
Rans = []
|
||||||
|
Wans = []
|
||||||
|
Eans = []
|
||||||
|
|
||||||
|
# Check for read availability.
|
||||||
|
for R in readlist:
|
||||||
|
if isinstance(R, int) or hasattr(R, 'fileno'):
|
||||||
|
# Python socket
|
||||||
|
if len(pyselect.select([R], [], [], 0.0)[0]) > 0:
|
||||||
|
Rans.append(R)
|
||||||
|
else:
|
||||||
|
# SAM Socket
|
||||||
|
if _has_data(R):
|
||||||
|
Rans.append(R)
|
||||||
|
# if R.type == i2p.socket.SOCK_STREAM:
|
||||||
|
# try:
|
||||||
|
# R._verify_connected()
|
||||||
|
# Rans.append(R)
|
||||||
|
# except:
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# if len(R.sessobj) > 0: Rans.append(R)
|
||||||
|
|
||||||
|
# Check for write availability.
|
||||||
|
for W in writelist:
|
||||||
|
if isinstance(W, int) or hasattr(W, 'fileno'):
|
||||||
|
# Python socket
|
||||||
|
if len(pyselect.select([], [W], [], 0.0)[1]) > 0:
|
||||||
|
Wans.append(W)
|
||||||
|
else:
|
||||||
|
# SAM Socket
|
||||||
|
if W.type == i2p.socket.SOCK_STREAM:
|
||||||
|
try:
|
||||||
|
W._verify_connected()
|
||||||
|
Wans.append(W)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Wans.append(W)
|
||||||
|
|
||||||
|
# Check for error conditions.
|
||||||
|
# These can only be stream errors.
|
||||||
|
for E in errlist:
|
||||||
|
if isinstance(E, int) or hasattr(E, 'fileno'):
|
||||||
|
# Python socket
|
||||||
|
if len(pyselect.select([], [], [E], 0.0)[2]) > 0:
|
||||||
|
Eans.append(E)
|
||||||
|
else:
|
||||||
|
if E.type == i2p.socket.SOCK_STREAM:
|
||||||
|
try:
|
||||||
|
# FIXME: Use a ._get_error() function for errors.
|
||||||
|
# Socket can only have an error if it connected.
|
||||||
|
E._verify_connected()
|
||||||
|
if E.sessobj.err != None:
|
||||||
|
Eans.append(E)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return (Rans, Wans, Eans)
|
||||||
|
|
||||||
|
|
||||||
def select(readlist, writelist, errlist, timeout=None):
|
def select(readlist, writelist, errlist, timeout=None):
|
||||||
"""Performs a select call. Works on SAM sockets and Python
|
"""Performs a select call. Works on SAM sockets and Python
|
||||||
sockets. See select.select() in the Python library for more
|
sockets. See select.select() in the Python library for more
|
||||||
information."""
|
information."""
|
||||||
Rans = []
|
|
||||||
Wans = []
|
|
||||||
Eans = []
|
|
||||||
if timeout != None: end = time.clock() + timeout
|
if timeout != None: end = time.clock() + timeout
|
||||||
while True:
|
while True:
|
||||||
# FIXME: Check performance.
|
# FIXME: Check performance.
|
||||||
# Use pyselect.poll for Python sockets, if needed for speed.
|
# Use pyselect.poll for Python sockets, if needed for speed.
|
||||||
|
(Rans, Wans, Eans) = _noblock_select(readlist,writelist,errlist)
|
||||||
|
|
||||||
# Check for read availability.
|
|
||||||
for R in readlist:
|
|
||||||
if isinstance(R, int) or hasattr(R, 'fileno'):
|
|
||||||
# Python socket
|
|
||||||
if len(pyselect.select([R], [], [], 0.0)[0]) > 0:
|
|
||||||
Rans.append(R)
|
|
||||||
else:
|
|
||||||
# SAM Socket
|
|
||||||
if R.type == i2p.socket.SOCK_STREAM:
|
|
||||||
try:
|
|
||||||
R._verify_connected()
|
|
||||||
Rans.append(R)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if len(R) > 0: Rans.append(R)
|
|
||||||
|
|
||||||
# Check for write availability.
|
|
||||||
for W in writelist:
|
|
||||||
if isinstance(W, int) or hasattr(W, 'fileno'):
|
|
||||||
# Python socket
|
|
||||||
if len(pyselect.select([], [W], [], 0.0)[1]) > 0:
|
|
||||||
Wans.append(W)
|
|
||||||
else:
|
|
||||||
# SAM Socket
|
|
||||||
if W.type == i2p.socket.SOCK_STREAM:
|
|
||||||
try:
|
|
||||||
W._verify_connected()
|
|
||||||
Wans.append(W)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
Wans.append(W)
|
|
||||||
|
|
||||||
# Check for error conditions.
|
|
||||||
# These can only be stream errors.
|
|
||||||
for E in errlist:
|
|
||||||
if isinstance(E, int) or hasattr(E, 'fileno'):
|
|
||||||
# Python socket
|
|
||||||
if len(pyselect.select([], [], [E], 0.0)[2]) > 0:
|
|
||||||
Eans.append(E)
|
|
||||||
else:
|
|
||||||
if E.type == i2p.socket.SOCK_STREAM:
|
|
||||||
try:
|
|
||||||
# FIXME: Use a ._get_error() function for errors.
|
|
||||||
# Socket can only have an error if it connected.
|
|
||||||
E._verify_connected()
|
|
||||||
if E.sessobj.err != None:
|
|
||||||
Eans.append(E)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if timeout != None and time.clock() >= end: break
|
if timeout != None and time.clock() >= end: break
|
||||||
if len(Rans) != 0 or len(Wans) != 0 or len(Eans) != 0: break
|
if len(Rans) != 0 or len(Wans) != 0 or len(Eans) != 0:
|
||||||
|
# One or more sockets are ready.
|
||||||
|
if timeout != 0.0:
|
||||||
|
# Check again, because sockets may have changed state while
|
||||||
|
# we did _noblock_select (it's safer to check twice, since
|
||||||
|
# they usually go from no data => data ready, and so forth).
|
||||||
|
(Rans, Wans, Eans) = _noblock_select(readlist, writelist,
|
||||||
|
errlist)
|
||||||
|
return (Rans, Wans, Eans)
|
||||||
|
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user