source: ipk/source.sh4/swapplayers_mediacenter_1.0/var/swap/extensions/MediaCenter/timeoutsocket.py@ 12073

Last change on this file since 12073 was 1013, checked in by civer, 16 years ago

[MediaCenter]

  • added WebRadioFS

!!! Not finished (just for Kingsize skin) etc etc...!!!

Please Test! :)

File size: 11.2 KB
Line 
1
2####
3# Copyright 2000,2001 by Timothy O'Malley <timo@alum.mit.edu>
4#
5# All Rights Reserved
6#
7# Permission to use, copy, modify, and distribute this software
8# and its documentation for any purpose and without fee is hereby
9# granted, provided that the above copyright notice appear in all
10# copies and that both that copyright notice and this permission
11# notice appear in supporting documentation, and that the name of
12# Timothy O'Malley not be used in advertising or publicity
13# pertaining to distribution of the software without specific, written
14# prior permission.
15#
16# Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18# AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR
19# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
22# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23# PERFORMANCE OF THIS SOFTWARE.
24#
25####
26
27"""Timeout Socket
28
29This module enables a timeout mechanism on all TCP connections. It
30does this by inserting a shim into the socket module. After this module
31has been imported, all socket creation goes through this shim. As a
32result, every TCP connection will support a timeout.
33
34The beauty of this method is that it immediately and transparently
35enables the entire python library to support timeouts on TCP sockets.
36As an example, if you wanted to SMTP connections to have a 20 second
37timeout:
38
39 import timeoutsocket
40 import smtplib
41 timeoutsocket.setDefaultSocketTimeout(20)
42
43
44The timeout applies to the socket functions that normally block on
45execution: read, write, connect, and accept. If any of these
46operations exceeds the specified timeout, the exception Timeout
47will be raised.
48
49The default timeout value is set to None. As a result, importing
50this module does not change the default behavior of a socket. The
51timeout mechanism only activates when the timeout has been set to
52a numeric value. (This behavior mimics the behavior of the
53select.select() function.)
54
55This module implements two classes: TimeoutSocket and TimeoutFile.
56
57The TimeoutSocket class defines a socket-like object that attempts to
58avoid the condition where a socket may block indefinitely. The
59TimeoutSocket class raises a Timeout exception whenever the
60current operation delays too long.
61
62The TimeoutFile class defines a file-like object that uses the TimeoutSocket
63class. When the makefile() method of TimeoutSocket is called, it returns
64an instance of a TimeoutFile.
65
66Each of these objects adds two methods to manage the timeout value:
67
68 get_timeout() --> returns the timeout of the socket or file
69 set_timeout() --> sets the timeout of the socket or file
70
71
72As an example, one might use the timeout feature to create httplib
73connections that will timeout after 30 seconds:
74
75 import timeoutsocket
76 import httplib
77 H = httplib.HTTP("www.python.org")
78 H.sock.set_timeout(30)
79
80Note: When used in this manner, the connect() routine may still
81block because it happens before the timeout is set. To avoid
82this, use the 'timeoutsocket.setDefaultSocketTimeout()' function.
83
84Good Luck!
85
86"""
87
88__version__ = "$Revision: 1.1 $"
89__author__ = "Timothy O'Malley <timo@alum.mit.edu>"
90
91#
92# Imports
93#
94import select, string
95import socket
96if not hasattr(socket, "_no_timeoutsocket"):
97 _socket = socket.socket
98else:
99 _socket = socket._no_timeoutsocket
100
101
102#
103# Set up constants to test for Connected and Blocking operations.
104# We delete 'os' and 'errno' to keep our namespace clean(er).
105# Thanks to Alex Martelli and G. Li for the Windows error codes.
106#
107import os
108if os.name == "nt":
109 _IsConnected = ( 10022, 10056 )
110 _ConnectBusy = ( 10035, )
111 _AcceptBusy = ( 10035, )
112else:
113 import errno
114 _IsConnected = ( errno.EISCONN, )
115 _ConnectBusy = ( errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK )
116 _AcceptBusy = ( errno.EAGAIN, errno.EWOULDBLOCK )
117 del errno
118del os
119
120#
121# Default timeout value for ALL TimeoutSockets
122#
123_DefaultTimeout = None
124def setDefaultSocketTimeout(timeout):
125 global _DefaultTimeout
126 _DefaultTimeout = timeout
127def getDefaultSocketTimeout():
128 return _DefaultTimeout
129
130#
131# Exceptions for socket errors and timeouts
132#
133Error = socket.error
134class Timeout(Exception):
135 pass
136
137#
138# Factory function
139#
140from socket import AF_INET, SOCK_STREAM
141def timeoutsocket(family=AF_INET, type=SOCK_STREAM, proto=None):
142 if family != AF_INET or type != SOCK_STREAM:
143 if proto:
144 return _socket(family, type, proto)
145 else:
146 return _socket(family, type)
147 return TimeoutSocket( _socket(family, type), _DefaultTimeout )
148# end timeoutsocket
149
150#
151# The TimeoutSocket class definition
152#
153class TimeoutSocket:
154 """TimeoutSocket object
155 Implements a socket-like object that raises Timeout whenever
156 an operation takes too long.
157 The definition of 'too long' can be changed using the
158 set_timeout() method.
159 """
160
161 _copies = 0
162 _blocking = 1
163
164 def __init__(self, sock, timeout):
165 self._sock = sock
166 self._timeout = timeout
167 # end __init__
168
169 def __getattr__(self, key):
170 return getattr(self._sock, key)
171 # end __getattr__
172
173 def get_timeout(self):
174 return self._timeout
175 # end set_timeout
176
177 def set_timeout(self, timeout=None):
178 self._timeout = timeout
179 # end set_timeout
180
181 def setblocking(self, blocking):
182 self._blocking = blocking
183 return self._sock.setblocking(blocking)
184 # end set_timeout
185
186 def connect_ex(self, addr):
187 errcode = 0
188 try:
189 self.connect(addr)
190 except Error, why:
191 errcode = why[0]
192 return errcode
193 # end connect_ex
194
195 def connect(self, addr, port=None, dumbhack=None):
196 # In case we were called as connect(host, port)
197 if port != None: addr = (addr, port)
198
199 # Shortcuts
200 sock = self._sock
201 timeout = self._timeout
202 blocking = self._blocking
203
204 # First, make a non-blocking call to connect
205 try:
206 sock.setblocking(0)
207 sock.connect(addr)
208 sock.setblocking(blocking)
209 return
210 except Error, why:
211 # Set the socket's blocking mode back
212 sock.setblocking(blocking)
213
214 # If we are not blocking, re-raise
215 if not blocking:
216 raise
217
218 # If we are already connected, then return success.
219 # If we got a genuine error, re-raise it.
220 errcode = why[0]
221 if dumbhack and errcode in _IsConnected:
222 return
223 elif errcode not in _ConnectBusy:
224 raise
225
226 # Now, wait for the connect to happen
227 # ONLY if dumbhack indicates this is pass number one.
228 # If select raises an error, we pass it on.
229 # Is this the right behavior?
230 if not dumbhack:
231 r,w,e = select.select([], [sock], [], timeout)
232 if w:
233 return self.connect(addr, dumbhack=1)
234
235 # If we get here, then we should raise Timeout
236 raise Timeout("Attempted connect to %s timed out." % str(addr) )
237 # end connect
238
239 def accept(self, dumbhack=None):
240 # Shortcuts
241 sock = self._sock
242 timeout = self._timeout
243 blocking = self._blocking
244
245 # First, make a non-blocking call to accept
246 # If we get a valid result, then convert the
247 # accept'ed socket into a TimeoutSocket.
248 # Be carefult about the blocking mode of ourselves.
249 try:
250 sock.setblocking(0)
251 newsock, addr = sock.accept()
252 sock.setblocking(blocking)
253 timeoutnewsock = self.__class__(newsock, timeout)
254 timeoutnewsock.setblocking(blocking)
255 return (timeoutnewsock, addr)
256 except Error, why:
257 # Set the socket's blocking mode back
258 sock.setblocking(blocking)
259 # If we are not supposed to block, then re-raise
260 if not blocking:
261 raise
262 # If we got a genuine error, re-raise it.
263 errcode = why[0]
264 if errcode not in _AcceptBusy:
265 raise
266 # Now, wait for the accept to happen
267 # ONLY if dumbhack indicates this is pass number one.
268 # If select raises an error, we pass it on.
269 # Is this the right behavior?
270 if not dumbhack:
271 r,w,e = select.select([sock], [], [], timeout)
272 if r:
273 return self.accept(dumbhack=1)
274
275 # If we get here, then we should raise Timeout
276 raise Timeout("Attempted accept timed out.")
277 # end accept
278
279 def send(self, data, flags=0):
280 sock = self._sock
281 if self._blocking:
282 r,w,e = select.select([],[sock],[], self._timeout)
283 if not w:
284 raise Timeout("Send timed out")
285 return sock.send(data, flags)
286 # end send
287
288 def recv(self, bufsize, flags=0):
289 sock = self._sock
290 if self._blocking:
291 r,w,e = select.select([sock], [], [], self._timeout)
292 if not r:
293 raise Timeout("Recv timed out")
294 return sock.recv(bufsize, flags)
295 # end recv
296
297 def makefile(self, flags="r", bufsize=-1):
298 self._copies = self._copies +1
299 return TimeoutFile(self, flags, bufsize)
300 # end makefile
301
302 def close(self):
303 if self._copies <= 0:
304 self._sock.close()
305 else:
306 self._copies = self._copies -1
307 # end close
308
309# end TimeoutSocket
310
311class TimeoutFile:
312 """TimeoutFile object
313 Implements a file-like object on top of TimeoutSocket.
314 """
315
316 def __init__(self, sock, mode="r", bufsize=4096):
317 self._sock = sock
318 self._bufsize = 4096
319 if bufsize > 0: self._bufsize = bufsize
320 if not hasattr(sock, "_inqueue"): self._sock._inqueue = ""
321
322 # end __init__
323
324 def __getattr__(self, key):
325 return getattr(self._sock, key)
326 # end __getattr__
327
328 def close(self):
329 self._sock.close()
330 self._sock = None
331 # end close
332
333 def write(self, data):
334 self.send(data)
335 # end write
336
337 def read(self, size=-1):
338 _sock = self._sock
339 _bufsize = self._bufsize
340 while 1:
341 datalen = len(_sock._inqueue)
342 if datalen >= size >= 0:
343 break
344 bufsize = _bufsize
345 if size > 0:
346 bufsize = min(bufsize, size - datalen )
347 buf = self.recv(bufsize)
348 if not buf:
349 break
350 _sock._inqueue = _sock._inqueue + buf
351 data = _sock._inqueue
352 _sock._inqueue = ""
353 if size > 0 and datalen > size:
354 _sock._inqueue = data[size:]
355 data = data[:size]
356 return data
357 # end read
358
359 def readline(self, size=-1):
360 _sock = self._sock
361 _bufsize = self._bufsize
362 while 1:
363 idx = string.find(_sock._inqueue, "\n")
364 if idx >= 0:
365 break
366 datalen = len(_sock._inqueue)
367 if datalen >= size >= 0:
368 break
369 bufsize = _bufsize
370 if size > 0:
371 bufsize = min(bufsize, size - datalen )
372 buf = self.recv(bufsize)
373 if not buf:
374 break
375 _sock._inqueue = _sock._inqueue + buf
376
377 data = _sock._inqueue
378 _sock._inqueue = ""
379 if idx >= 0:
380 idx = idx + 1
381 _sock._inqueue = data[idx:]
382 data = data[:idx]
383 elif size > 0 and datalen > size:
384 _sock._inqueue = data[size:]
385 data = data[:size]
386 return data
387 # end readline
388
389 def readlines(self, sizehint=-1):
390 result = []
391 data = self.read()
392 while data:
393 idx = string.find(data, "\n")
394 if idx >= 0:
395 idx = idx + 1
396 result.append( data[:idx] )
397 data = data[idx:]
398 else:
399 result.append( data )
400 data = ""
401 return result
402 # end readlines
403
404 def flush(self): pass
405# end TimeoutFile
406
407#
408# Silently replace the socket() builtin function with
409# our timeoutsocket() definition.
410#
411if not hasattr(socket, "_no_timeoutsocket"):
412 socket._no_timeoutsocket = socket.socket
413 socket.socket = timeoutsocket
414del socket
415socket = timeoutsocket
416# Finis
Note: See TracBrowser for help on using the repository browser.