1 """Based on code from timeout_socket.py, with some tweaks for compatibility.
2 These tweaks should really be rolled back into timeout_socket, but it's
3 not totally clear who is maintaining it at this point. In the meantime,
4 we'll use a different module name for our tweaked version to avoid any
7 The original timeout_socket is by:
9 Scott Cotton <scott@chronis.pobox.com>
10 Lloyd Zusman <ljz@asfast.com>
11 Phil Mayes <pmayes@olivebr.com>
12 Piers Lauder <piers@cs.su.oz.au>
13 Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk>
18 import string, socket, select, errno
20 WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022)
24 """A socket imposter that supports timeout limits."""
26 def __init__(self, timeout=20, sock=None):
27 self.timeout = float(timeout)
30 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
32 self.sock.setblocking(0)
36 def __getattr__(self, name):
37 # Delegate to real socket attributes.
38 return getattr(self.sock, name)
40 def connect(self, *addr):
41 timeout = self.timeout
46 apply(sock.connect, addr)
47 sock.setblocking(timeout != 0)
49 except socket.error,why:
53 if len(why.args) == 1:
58 errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK
61 r,w,e = select.select([],[sock],[],timeout)
64 apply(sock.connect, addr)
66 except socket.error,why:
67 if len(why.args) == 1:
71 if code in (errno.EISCONN, WSAEINVAL):
74 raise TimeoutError('socket connect() timeout.')
76 def send(self, data, flags=0):
80 r, w, e = select.select([],[self.sock], [], self.timeout)
82 buff = data[next:next + 8192]
83 sent = self.sock.send(buff, flags)
88 raise TimeoutError('socket send() timeout.')
90 def recv(self, amt, flags=0):
91 if select.select([self.sock], [], [], self.timeout)[0]:
92 return self.sock.recv(amt, flags)
93 raise TimeoutError('socket recv() timeout.')
98 def makefile(self, mode="r", buffsize=-1):
99 self.handles = self.handles + 1
104 self.handles = self.handles - 1
105 if self.handles == 0 and self.sock.fileno() >= 0:
108 def read(self, n=-1):
109 if not isinstance(n, type(1)):
114 data = self._rbuf[:n]
115 self._rbuf = self._rbuf[n:]
121 new = self.recv(max(n, self.buffsize))
131 k = max(4096, self.buffsize)
138 k = min(k*2, 1024**2)
141 def readline(self, limit=-1):
143 i = self._rbuf.find('\n')
144 while i < 0 and not (0 < limit <= len(self._rbuf)):
145 new = self.recv(self.buffsize)
148 if i >= 0: i = i + len(self._rbuf)
149 self._rbuf = self._rbuf + new
150 if i < 0: i = len(self._rbuf)
152 if 0 <= limit < len(self._rbuf): i = limit
153 data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
156 def readlines(self, sizehint = 0):
160 line = self.readline()
164 if sizehint and total >= sizehint:
168 def writelines(self, list):
169 self.send(''.join(list))
171 def write(self, data):
178 class TimeoutError(Exception):