]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/python/socket.py
/sys/lib/dist/ndb/common: correct authdom=inri
[plan9front.git] / sys / lib / python / socket.py
1 # Wrapper module for _socket, providing some additional facilities
2 # implemented in Python.
3
4 """\
5 This module provides socket operations and some related functions.
6 On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
7 On other systems, it only supports IP. Functions specific for a
8 socket are available as methods of the socket object.
9
10 Functions:
11
12 socket() -- create a new socket object
13 socketpair() -- create a pair of new socket objects [*]
14 fromfd() -- create a socket object from an open file descriptor [*]
15 gethostname() -- return the current hostname
16 gethostbyname() -- map a hostname to its IP number
17 gethostbyaddr() -- map an IP number or hostname to DNS info
18 getservbyname() -- map a service name and a protocol name to a port number
19 getprotobyname() -- mape a protocol name (e.g. 'tcp') to a number
20 ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
21 htons(), htonl() -- convert 16, 32 bit int from host to network byte order
22 inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
23 inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
24 ssl() -- secure socket layer support (only available if configured)
25 socket.getdefaulttimeout() -- get the default timeout value
26 socket.setdefaulttimeout() -- set the default timeout value
27
28  [*] not available on all platforms!
29
30 Special objects:
31
32 SocketType -- type object for socket objects
33 error -- exception raised for I/O errors
34 has_ipv6 -- boolean value indicating if IPv6 is supported
35
36 Integer constants:
37
38 AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
39 SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)
40
41 Many other constants may be defined; these may be used in calls to
42 the setsockopt() and getsockopt() methods.
43 """
44
45 import _socket
46 from _socket import *
47
48 _have_ssl = False
49 try:
50     import _ssl
51     from _ssl import *
52     _have_ssl = True
53 except ImportError:
54     pass
55
56 import os, sys
57
58 try:
59     from errno import EBADF
60 except ImportError:
61     EBADF = 9
62
63 __all__ = ["getfqdn"]
64 __all__.extend(os._get_exports_list(_socket))
65 if _have_ssl:
66     __all__.extend(os._get_exports_list(_ssl))
67
68 _realsocket = socket
69 if _have_ssl:
70     _realssl = ssl
71     def ssl(sock, keyfile=None, certfile=None):
72         if hasattr(sock, "_sock"):
73             sock = sock._sock
74         return _realssl(sock, keyfile, certfile)
75
76 # WSA error codes
77 if sys.platform.lower().startswith("win"):
78     errorTab = {}
79     errorTab[10004] = "The operation was interrupted."
80     errorTab[10009] = "A bad file handle was passed."
81     errorTab[10013] = "Permission denied."
82     errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
83     errorTab[10022] = "An invalid operation was attempted."
84     errorTab[10035] = "The socket operation would block"
85     errorTab[10036] = "A blocking operation is already in progress."
86     errorTab[10048] = "The network address is in use."
87     errorTab[10054] = "The connection has been reset."
88     errorTab[10058] = "The network has been shut down."
89     errorTab[10060] = "The operation timed out."
90     errorTab[10061] = "Connection refused."
91     errorTab[10063] = "The name is too long."
92     errorTab[10064] = "The host is down."
93     errorTab[10065] = "The host is unreachable."
94     __all__.append("errorTab")
95
96
97
98 def getfqdn(name=''):
99     """Get fully qualified domain name from name.
100
101     An empty argument is interpreted as meaning the local host.
102
103     First the hostname returned by gethostbyaddr() is checked, then
104     possibly existing aliases. In case no FQDN is available, hostname
105     from gethostname() is returned.
106     """
107     name = name.strip()
108     if not name or name == '0.0.0.0':
109         name = gethostname()
110     try:
111         hostname, aliases, ipaddrs = gethostbyaddr(name)
112     except error:
113         pass
114     else:
115         aliases.insert(0, hostname)
116         for name in aliases:
117             if '.' in name:
118                 break
119         else:
120             name = hostname
121     return name
122
123
124 _socketmethods = (
125     'bind', 'connect', 'connect_ex', 'fileno', 'listen',
126     'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
127     'sendall', 'setblocking',
128     'settimeout', 'gettimeout', 'shutdown')
129
130 if sys.platform == "riscos":
131     _socketmethods = _socketmethods + ('sleeptaskw',)
132
133 # All the method names that must be delegated to either the real socket
134 # object or the _closedsocket object.
135 _delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into",
136                      "send", "sendto")
137
138 class _closedsocket(object):
139     __slots__ = []
140     def _dummy(*args):
141         raise error(EBADF, 'Bad file descriptor')
142     # All _delegate_methods must also be initialized here.
143     send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
144     __getattr__ = _dummy
145
146 class _socketobject(object):
147
148     __doc__ = _realsocket.__doc__
149
150     __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
151
152     def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
153         if _sock is None:
154             _sock = _realsocket(family, type, proto)
155         self._sock = _sock
156         for method in _delegate_methods:
157             setattr(self, method, getattr(_sock, method))
158
159     def close(self):
160         self._sock = _closedsocket()
161         dummy = self._sock._dummy
162         for method in _delegate_methods:
163             setattr(self, method, dummy)
164     close.__doc__ = _realsocket.close.__doc__
165
166     def accept(self):
167         sock, addr = self._sock.accept()
168         return _socketobject(_sock=sock), addr
169     accept.__doc__ = _realsocket.accept.__doc__
170
171     def dup(self):
172         """dup() -> socket object
173
174         Return a new socket object connected to the same system resource."""
175         return _socketobject(_sock=self._sock)
176
177     def makefile(self, mode='r', bufsize=-1):
178         """makefile([mode[, bufsize]]) -> file object
179
180         Return a regular file object corresponding to the socket.  The mode
181         and bufsize arguments are as for the built-in open() function."""
182         return _fileobject(self._sock, mode, bufsize)
183
184     family = property(lambda self: self._sock.family, doc="the socket family")
185     type = property(lambda self: self._sock.type, doc="the socket type")
186     proto = property(lambda self: self._sock.proto, doc="the socket protocol")
187
188     _s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
189           "%s.__doc__ = _realsocket.%s.__doc__\n")
190     for _m in _socketmethods:
191         exec _s % (_m, _m, _m, _m)
192     del _m, _s
193
194 socket = SocketType = _socketobject
195
196 class _fileobject(object):
197     """Faux file object attached to a socket object."""
198
199     default_bufsize = 8192
200     name = "<socket>"
201
202     __slots__ = ["mode", "bufsize", "softspace",
203                  # "closed" is a property, see below
204                  "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf",
205                  "_close"]
206
207     def __init__(self, sock, mode='rb', bufsize=-1, close=False):
208         self._sock = sock
209         self.mode = mode # Not actually used in this version
210         if bufsize < 0:
211             bufsize = self.default_bufsize
212         self.bufsize = bufsize
213         self.softspace = False
214         if bufsize == 0:
215             self._rbufsize = 1
216         elif bufsize == 1:
217             self._rbufsize = self.default_bufsize
218         else:
219             self._rbufsize = bufsize
220         self._wbufsize = bufsize
221         self._rbuf = "" # A string
222         self._wbuf = [] # A list of strings
223         self._close = close
224
225     def _getclosed(self):
226         return self._sock is None
227     closed = property(_getclosed, doc="True if the file is closed")
228
229     def close(self):
230         try:
231             if self._sock:
232                 self.flush()
233         finally:
234             if self._close:
235                 self._sock.close()
236             self._sock = None
237
238     def __del__(self):
239         try:
240             self.close()
241         except:
242             # close() may fail if __init__ didn't complete
243             pass
244
245     def flush(self):
246         if self._wbuf:
247             buffer = "".join(self._wbuf)
248             self._wbuf = []
249             self._sock.sendall(buffer)
250
251     def fileno(self):
252         return self._sock.fileno()
253
254     def write(self, data):
255         data = str(data) # XXX Should really reject non-string non-buffers
256         if not data:
257             return
258         self._wbuf.append(data)
259         if (self._wbufsize == 0 or
260             self._wbufsize == 1 and '\n' in data or
261             self._get_wbuf_len() >= self._wbufsize):
262             self.flush()
263
264     def writelines(self, list):
265         # XXX We could do better here for very long lists
266         # XXX Should really reject non-string non-buffers
267         self._wbuf.extend(filter(None, map(str, list)))
268         if (self._wbufsize <= 1 or
269             self._get_wbuf_len() >= self._wbufsize):
270             self.flush()
271
272     def _get_wbuf_len(self):
273         buf_len = 0
274         for x in self._wbuf:
275             buf_len += len(x)
276         return buf_len
277
278     def read(self, size=-1):
279         data = self._rbuf
280         if size < 0:
281             # Read until EOF
282             buffers = []
283             if data:
284                 buffers.append(data)
285             self._rbuf = ""
286             if self._rbufsize <= 1:
287                 recv_size = self.default_bufsize
288             else:
289                 recv_size = self._rbufsize
290             while True:
291                 data = self._sock.recv(recv_size)
292                 if not data:
293                     break
294                 buffers.append(data)
295             return "".join(buffers)
296         else:
297             # Read until size bytes or EOF seen, whichever comes first
298             buf_len = len(data)
299             if buf_len >= size:
300                 self._rbuf = data[size:]
301                 return data[:size]
302             buffers = []
303             if data:
304                 buffers.append(data)
305             self._rbuf = ""
306             while True:
307                 left = size - buf_len
308                 recv_size = max(self._rbufsize, left)
309                 data = self._sock.recv(recv_size)
310                 if not data:
311                     break
312                 buffers.append(data)
313                 n = len(data)
314                 if n >= left:
315                     self._rbuf = data[left:]
316                     buffers[-1] = data[:left]
317                     break
318                 buf_len += n
319             return "".join(buffers)
320
321     def readline(self, size=-1):
322         data = self._rbuf
323         if size < 0:
324             # Read until \n or EOF, whichever comes first
325             if self._rbufsize <= 1:
326                 # Speed up unbuffered case
327                 assert data == ""
328                 buffers = []
329                 recv = self._sock.recv
330                 while data != "\n":
331                     data = recv(1)
332                     if not data:
333                         break
334                     buffers.append(data)
335                 return "".join(buffers)
336             nl = data.find('\n')
337             if nl >= 0:
338                 nl += 1
339                 self._rbuf = data[nl:]
340                 return data[:nl]
341             buffers = []
342             if data:
343                 buffers.append(data)
344             self._rbuf = ""
345             while True:
346                 data = self._sock.recv(self._rbufsize)
347                 if not data:
348                     break
349                 buffers.append(data)
350                 nl = data.find('\n')
351                 if nl >= 0:
352                     nl += 1
353                     self._rbuf = data[nl:]
354                     buffers[-1] = data[:nl]
355                     break
356             return "".join(buffers)
357         else:
358             # Read until size bytes or \n or EOF seen, whichever comes first
359             nl = data.find('\n', 0, size)
360             if nl >= 0:
361                 nl += 1
362                 self._rbuf = data[nl:]
363                 return data[:nl]
364             buf_len = len(data)
365             if buf_len >= size:
366                 self._rbuf = data[size:]
367                 return data[:size]
368             buffers = []
369             if data:
370                 buffers.append(data)
371             self._rbuf = ""
372             while True:
373                 data = self._sock.recv(self._rbufsize)
374                 if not data:
375                     break
376                 buffers.append(data)
377                 left = size - buf_len
378                 nl = data.find('\n', 0, left)
379                 if nl >= 0:
380                     nl += 1
381                     self._rbuf = data[nl:]
382                     buffers[-1] = data[:nl]
383                     break
384                 n = len(data)
385                 if n >= left:
386                     self._rbuf = data[left:]
387                     buffers[-1] = data[:left]
388                     break
389                 buf_len += n
390             return "".join(buffers)
391
392     def readlines(self, sizehint=0):
393         total = 0
394         list = []
395         while True:
396             line = self.readline()
397             if not line:
398                 break
399             list.append(line)
400             total += len(line)
401             if sizehint and total >= sizehint:
402                 break
403         return list
404
405     # Iterator protocols
406
407     def __iter__(self):
408         return self
409
410     def next(self):
411         line = self.readline()
412         if not line:
413             raise StopIteration
414         return line