socket.py 12.1 KB
Newer Older
1 2 3 4 5 6
# Wrapper module for _socket, providing some additional facilities
# implemented in Python.

"""\
This module provides socket operations and some related functions.
On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
Tim Peters's avatar
Tim Peters committed
7
On other systems, it only supports IP. Functions specific for a
8
socket are available as methods of the socket object.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Functions:

socket() -- create a new socket object
fromfd() -- create a socket object from an open file descriptor [*]
gethostname() -- return the current hostname
gethostbyname() -- map a hostname to its IP number
gethostbyaddr() -- map an IP number or hostname to DNS info
getservbyname() -- map a service name and a protocol name to a port number
getprotobyname() -- mape a protocol name (e.g. 'tcp') to a number
ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
htons(), htonl() -- convert 16, 32 bit int from host to network byte order
inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
ssl() -- secure socket layer support (only available if configured)
24 25
socket.getdefaulttimeout() -- get the default timeout value
socket.setdefaulttimeout() -- set the default timeout value
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

 [*] not available on all platforms!

Special objects:

SocketType -- type object for socket objects
error -- exception raised for I/O errors

Integer constants:

AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)

Many other constants may be defined; these may be used in calls to
the setsockopt() and getsockopt() methods.
"""

43
import _socket
44
from _socket import *
45

46
_have_ssl = False
47
try:
48
    import _ssl
49
    from _ssl import *
50
    _have_ssl = True
51
except ImportError:
52
    pass
53 54 55

import os, sys

56 57
__all__ = ["getfqdn"]
__all__.extend(os._get_exports_list(_socket))
58 59
if _have_ssl:
    __all__.extend(os._get_exports_list(_ssl))
60

61 62
_realsocket = socket
_needwrapper = False
63
if (sys.platform.lower().startswith("win")
64
    or (hasattr(os, 'uname') and os.uname()[0] == "BeOS")
65
    or sys.platform=="riscos"):
66

67
    _needwrapper = True
68

69 70
    if _have_ssl:
        _realssl = ssl
71 72 73
        def ssl(sock, keyfile=None, certfile=None):
            if hasattr(sock, "_sock"):
                sock = sock._sock
74
            return _realssl(sock, keyfile, certfile)
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

# WSA error codes
if sys.platform.lower().startswith("win"):
    errorTab = {}
    errorTab[10004] = "The operation was interrupted."
    errorTab[10009] = "A bad file handle was passed."
    errorTab[10013] = "Permission denied."
    errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
    errorTab[10022] = "An invalid operation was attempted."
    errorTab[10035] = "The socket operation would block"
    errorTab[10036] = "A blocking operation is already in progress."
    errorTab[10048] = "The network address is in use."
    errorTab[10054] = "The connection has been reset."
    errorTab[10058] = "The network has been shut down."
    errorTab[10060] = "The operation timed out."
    errorTab[10061] = "Connection refused."
    errorTab[10063] = "The name is too long."
    errorTab[10064] = "The host is down."
    errorTab[10065] = "The host is unreachable."
94
    __all__.append("errorTab")
95

96 97 98 99 100 101 102 103 104 105 106 107 108
del os, sys


def getfqdn(name=''):
    """Get fully qualified domain name from name.

    An empty argument is interpreted as meaning the local host.

    First the hostname returned by gethostbyaddr() is checked, then
    possibly existing aliases. In case no FQDN is available, hostname
    is returned.
    """
    name = name.strip()
109
    if not name or name == '0.0.0.0':
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        name = gethostname()
    try:
        hostname, aliases, ipaddrs = gethostbyaddr(name)
    except error:
        pass
    else:
        aliases.insert(0, hostname)
        for name in aliases:
            if '.' in name:
                break
        else:
            name = hostname
    return name


#
# These classes are used by the socket() defined on Windows and BeOS
# platforms to provide a best-effort implementation of the cleanup
# semantics needed when sockets can't be dup()ed.
#
# These are not actually used on other platforms.
#

133 134 135
_socketmethods = (
    'bind', 'connect', 'connect_ex', 'fileno', 'listen',
    'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
136 137
    'recv', 'recvfrom', 'send', 'sendall', 'sendto', 'setblocking',
    'settimeout', 'gettimeout', 'shutdown')
138

139 140 141 142 143
class _closedsocket(object):
    __slots__ = []
    def __getattr__(self, name):
        raise error(9, 'Bad file descriptor')

144 145 146
class _socketobject(object):

    __doc__ = _realsocket.__doc__
147

148 149 150 151
    __slots__ = ["_sock"]

    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
        if _sock is None:
152
            _sock = _realsocket(family, type, proto)
153
        self._sock = _sock
154 155

    def close(self):
156
        self._sock = _closedsocket()
157
    close.__doc__ = _realsocket.close.__doc__
158 159 160

    def accept(self):
        sock, addr = self._sock.accept()
161 162
        return _socketobject(_sock=sock), addr
    accept.__doc__ = _realsocket.accept.__doc__
163 164

    def dup(self):
165 166 167 168
        """dup() -> socket object

        Return a new socket object connected to the same system resource."""
        return _socketobject(_sock=self._sock)
169 170

    def makefile(self, mode='r', bufsize=-1):
171 172 173 174
        """makefile([mode[, bufsize]]) -> file object

        Return a regular file object corresponding to the socket.  The mode
        and bufsize arguments are as for the built-in open() function."""
175 176
        return _fileobject(self._sock, mode, bufsize)

177 178
    _s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
          "%s.__doc__ = _realsocket.%s.__doc__\n")
179
    for _m in _socketmethods:
180
        exec _s % (_m, _m, _m, _m)
181
    del _m, _s
182

183 184
if _needwrapper:
    socket = _socketobject
185

186
class _fileobject(object):
187 188 189
    """Faux file object attached to a socket object."""

    default_bufsize = 8192
190 191 192 193 194
    name = "<socket>"

    __slots__ = ["mode", "bufsize", "softspace",
                 # "closed" is a property, see below
                 "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf"]
195

196
    def __init__(self, sock, mode='rb', bufsize=-1):
197
        self._sock = sock
198
        self.mode = mode # Not actually used in this version
199 200
        if bufsize < 0:
            bufsize = self.default_bufsize
201 202
        self.bufsize = bufsize
        self.softspace = False
203 204 205 206 207 208
        if bufsize == 0:
            self._rbufsize = 1
        elif bufsize == 1:
            self._rbufsize = self.default_bufsize
        else:
            self._rbufsize = bufsize
209
        self._wbufsize = bufsize
210 211
        self._rbuf = "" # A string
        self._wbuf = [] # A list of strings
212

213 214 215 216
    def _getclosed(self):
        return self._sock is not None
    closed = property(_getclosed, doc="True if the file is closed")

217 218 219 220 221
    def close(self):
        try:
            if self._sock:
                self.flush()
        finally:
222
            self._sock = None
223 224 225 226 227 228

    def __del__(self):
        self.close()

    def flush(self):
        if self._wbuf:
229 230
            buffer = "".join(self._wbuf)
            self._wbuf = []
231
            self._sock.sendall(buffer)
232

Neal Norwitz's avatar
Neal Norwitz committed
233
    def fileno(self):
234 235 236
        return self._sock.fileno()

    def write(self, data):
237 238 239 240 241 242 243
        data = str(data) # XXX Should really reject non-string non-buffers
        if not data:
            return
        self._wbuf.append(data)
        if (self._wbufsize == 0 or
            self._wbufsize == 1 and '\n' in data or
            self._get_wbuf_len() >= self._wbufsize):
244
            self.flush()
245 246

    def writelines(self, list):
247 248 249 250 251 252
        # XXX We could do better here for very long lists
        # XXX Should really reject non-string non-buffers
        self._wbuf.extend(filter(None, map(str, list)))
        if (self._wbufsize <= 1 or
            self._get_wbuf_len() >= self._wbufsize):
            self.flush()
253

254
    def _get_wbuf_len(self):
255
        buf_len = 0
256 257
        for x in self._wbuf:
            buf_len += len(x)
258 259 260
        return buf_len

    def read(self, size=-1):
261
        data = self._rbuf
262 263
        if size < 0:
            # Read until EOF
264 265 266 267
            buffers = []
            if data:
                buffers.append(data)
            self._rbuf = ""
268 269 270 271
            if self._rbufsize <= 1:
                recv_size = self.default_bufsize
            else:
                recv_size = self._rbufsize
272
            while True:
273 274 275
                data = self._sock.recv(recv_size)
                if not data:
                    break
276 277
                buffers.append(data)
            return "".join(buffers)
278
        else:
279 280 281 282 283 284 285 286 287 288 289 290
            # Read until size bytes or EOF seen, whichever comes first
            buf_len = len(data)
            if buf_len >= size:
                self._rbuf = data[size:]
                return data[:size]
            buffers = []
            if data:
                buffers.append(data)
            self._rbuf = ""
            while True:
                left = size - buf_len
                recv_size = max(self._rbufsize, left)
291 292 293
                data = self._sock.recv(recv_size)
                if not data:
                    break
294 295 296 297 298 299 300 301
                buffers.append(data)
                n = len(data)
                if n >= left:
                    self._rbuf = data[left:]
                    buffers[-1] = data[:left]
                    break
                buf_len += n
            return "".join(buffers)
302 303

    def readline(self, size=-1):
304 305 306
        data = self._rbuf
        if size < 0:
            # Read until \n or EOF, whichever comes first
307 308 309 310 311 312 313 314 315 316 317
            if self._rbufsize <= 1:
                # Speed up unbuffered case
                assert data == ""
                buffers = []
                recv = self._sock.recv
                while data != "\n":
                    data = recv(1)
                    if not data:
                        break
                    buffers.append(data)
                return "".join(buffers)
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
            nl = data.find('\n')
            if nl >= 0:
                nl += 1
                self._rbuf = data[nl:]
                return data[:nl]
            buffers = []
            if data:
                buffers.append(data)
            self._rbuf = ""
            while True:
                data = self._sock.recv(self._rbufsize)
                if not data:
                    break
                buffers.append(data)
                nl = data.find('\n')
                if nl >= 0:
                    nl += 1
                    self._rbuf = data[nl:]
                    buffers[-1] = data[:nl]
                    break
            return "".join(buffers)
339
        else:
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
            # Read until size bytes or \n or EOF seen, whichever comes first
            nl = data.find('\n', 0, size)
            if nl >= 0:
                nl += 1
                self._rbuf = data[nl:]
                return data[:nl]
            buf_len = len(data)
            if buf_len >= size:
                self._rbuf = data[size:]
                return data[:size]
            buffers = []
            if data:
                buffers.append(data)
            self._rbuf = ""
            while True:
                data = self._sock.recv(self._rbufsize)
                if not data:
                    break
                buffers.append(data)
                left = size - buf_len
                nl = data.find('\n', 0, left)
                if nl >= 0:
                    nl += 1
                    self._rbuf = data[nl:]
                    buffers[-1] = data[:nl]
                    break
                n = len(data)
                if n >= left:
                    self._rbuf = data[left:]
                    buffers[-1] = data[:left]
                    break
                buf_len += n
            return "".join(buffers)
373

374
    def readlines(self, sizehint=0):
375
        total = 0
376
        list = []
377
        while True:
378
            line = self.readline()
Neal Norwitz's avatar
Neal Norwitz committed
379 380
            if not line:
                break
381
            list.append(line)
382 383 384
            total += len(line)
            if sizehint and total >= sizehint:
                break
385
        return list
386 387 388 389 390 391 392 393 394 395 396

    # Iterator protocols

    def __iter__(self):
        return self

    def next(self):
        line = self.readline()
        if not line:
            raise StopIteration
        return line