From: Fred Drake <fdrake@acm.org>
Date: Wed, 16 Aug 2000 14:14:32 +0000 (+0000)
Subject: Revise the wrapper structure for the socket module:
X-Git-Tag: v2.0b1~424
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6070f0221c0f4f2bb0fea518ea6e0b5e9497271;p=python

Revise the wrapper structure for the socket module:

socket.py is used for all platforms, and it defines the additional
classes and alternate socket() function for Windows and BeOS systems.

The plat-*/socket.py files are no longer needed, since there is a
shared socket.py.

make_fqdn() is provided, but I decided to call it getfqdn() to be
consistent with the other names in the socket module.  Since it is
really a "get" operation and does not create a new name, this is
the right name to give it.

Move the docstring here from the _socket module.
---

diff --git a/Lib/plat-beos/socket.py b/Lib/plat-beos/socket.py
deleted file mode 100644
index d3d26ed4db..0000000000
--- a/Lib/plat-beos/socket.py
+++ /dev/null
@@ -1,133 +0,0 @@
-"Socket wrapper for BeOS, which does not support dup()."
-
-# (And hence, fromfd() and makefile() are unimplemented in C....)
-
-# XXX Living dangerously here -- close() is implemented by deleting a
-# reference.  Thus we rely on the real _socket module to close on
-# deallocation, and also hope that nobody keeps a reference to our _sock
-# member.
-
-
-
-try:
-    from _socket import *
-except ImportError:
-    from socket import *
-
-_realsocketcall = socket
-
-
-def socket(family, type, proto=0):
-    return _socketobject(_realsocketcall(family, type, proto))
-
-
-class _socketobject:
-
-    def __init__(self, sock):
-        self._sock = sock
-
-    def close(self):
-        self._sock = 0
-
-    def __del__(self):
-        self.close()
-
-    def accept(self):
-        sock, addr = self._sock.accept()
-        return _socketobject(sock), addr
-
-    def dup(self):
-        return _socketobject(self._sock)
-
-    def makefile(self, mode='r', bufsize=-1):
-        return _fileobject(self._sock, mode, bufsize)
-
-    _s = "def %s(self, *args): return apply(self._sock.%s, args)\n\n"
-    for _m in ('bind', 'connect', 'fileno', 'listen',
-               'getpeername', 'getsockname',
-               'getsockopt', 'setsockopt',
-               'recv', 'recvfrom', 'send', 'sendto',
-               'setblocking',
-               'shutdown'):
-        exec _s % (_m, _m)
-
-
-class _fileobject:
-
-    def __init__(self, sock, mode, bufsize):
-        self._sock = sock
-        self._mode = mode
-        if bufsize < 0:
-            bufsize = 512
-        self._rbufsize = max(1, bufsize)
-        self._wbufsize = bufsize
-        self._wbuf = self._rbuf = ""
-
-    def close(self):
-        try:
-            if self._sock:
-                self.flush()
-        finally:
-            self._sock = 0
-
-    def __del__(self):
-        self.close()
-
-    def flush(self):
-        if self._wbuf:
-            self._sock.send(self._wbuf)
-            self._wbuf = ""
-
-    def fileno(self):
-        return self._sock.fileno()
-
-    def write(self, data):
-        self._wbuf = self._wbuf + data
-        if self._wbufsize == 1:
-            if '\n' in data:
-                self.flush()
-        else:
-            if len(self._wbuf) >= self._wbufsize:
-                self.flush()
-
-    def writelines(self, list):
-        filter(self._sock.send, list)
-        self.flush()
-
-    def read(self, n=-1):
-        if n >= 0:
-            while len(self._rbuf) < n:
-                new = self._sock.recv(self._rbufsize)
-                if not new: break
-                self._rbuf = self._rbuf + new
-            data, self._rbuf = self._rbuf[:n], self._rbuf[n:]
-            return data
-        while 1:
-            new = self._sock.recv(self._rbufsize)
-            if not new: break
-            self._rbuf = self._rbuf + new
-        data, self._rbuf = self._rbuf, ""
-        return data
-
-    def readline(self):
-        import string
-        data = ""
-        i = string.find(self._rbuf, '\n')
-        while i < 0:
-            new = self._sock.recv(self._rbufsize)
-            if not new: break
-            i = string.find(new, '\n')
-            if i >= 0: i = i + len(self._rbuf)
-            self._rbuf = self._rbuf + new
-        if i < 0: i = len(self._rbuf)
-        else: i = i+1
-        data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
-        return data
-
-    def readlines(self):
-        list = []
-        while 1:
-            line = self.readline()
-            if not line: break
-            list.append(line)
-        return list
diff --git a/Lib/plat-win/socket.py b/Lib/plat-win/socket.py
deleted file mode 100755
index 0410aa7966..0000000000
--- a/Lib/plat-win/socket.py
+++ /dev/null
@@ -1,168 +0,0 @@
-"Socket wrapper for Windows, which does not support dup()."
-
-# (And hence, fromfd() and makefile() are unimplemented in C....)
-
-# XXX Living dangerously here -- close() is implemented by deleting a
-# reference.  Thus we rely on the real _socket module to close on
-# deallocation, and also hope that nobody keeps a reference to our _sock
-# member.
-
-
-
-try:
-	from _socket import *
-except ImportError:
-	from socket import *
-
-_realsocketcall = socket
-
-
-def socket(family, type, proto=0):
-	return _socketobject(_realsocketcall(family, type, proto))
-
-
-class _socketobject:
-
-	def __init__(self, sock):
-		self._sock = sock
-
-	def close(self):
-		self._sock = 0
-
-	def __del__(self):
-		self.close()
-
-	def accept(self):
-		sock, addr = self._sock.accept()
-		return _socketobject(sock), addr
-
-	def dup(self):
-		return _socketobject(self._sock)
-
-	def makefile(self, mode='r', bufsize=-1):
-		return _fileobject(self._sock, mode, bufsize)
-
-	_s = "def %s(self, *args): return apply(self._sock.%s, args)\n\n"
-	for _m in ('bind', 'connect', 'connect_ex', 'fileno', 'listen',
-		   'getpeername', 'getsockname',
-		   'getsockopt', 'setsockopt',
-		   'recv', 'recvfrom', 'send', 'sendto',
-		   'setblocking',
-		   'shutdown'):
-		exec _s % (_m, _m)
-
-
-class _fileobject:
-
-	def __init__(self, sock, mode, bufsize):
-		self._sock = sock
-		self._mode = mode
-		if bufsize < 0:
-			bufsize = 512
-		self._rbufsize = max(1, bufsize)
-		self._wbufsize = bufsize
-		self._wbuf = self._rbuf = ""
-
-	def close(self):
-		try:
-			if self._sock:
-				self.flush()
-		finally:
-			self._sock = 0
-
-	def __del__(self):
-		self.close()
-
-	def flush(self):
-		if self._wbuf:
-			self._sock.send(self._wbuf)
-			self._wbuf = ""
-
-	def fileno(self):
-		return self._sock.fileno()
-
-	def write(self, data):
-		self._wbuf = self._wbuf + data
-		if self._wbufsize == 1:
-			if '\n' in data:
-				self.flush()
-		else:
-			if len(self._wbuf) >= self._wbufsize:
-				self.flush()
-
-	def writelines(self, list):
-		filter(self._sock.send, list)
-		self.flush()
-
-	def read(self, n=-1):
-		if n >= 0:
-			k = len(self._rbuf)
-			if n <= k:
-				data = self._rbuf[:n]
-				self._rbuf = self._rbuf[n:]
-				return data
-			n = n - k
-			l = [self._rbuf]
-			self._rbuf = ""
-			while n > 0:
-				new = self._sock.recv(max(n, self._rbufsize))
-				if not new: break
-				k = len(new)
-				if k > n:
-					l.append(new[:n])
-					self._rbuf = new[n:]
-					break
-				l.append(new)
-				n = n - k
-			return "".join(l)
-		k = max(512, self._rbufsize)
-		l = [self._rbuf]
-		self._rbuf = ""
-		while 1:
-			new = self._sock.recv(k)
-			if not new: break
-			l.append(new)
-			k = min(k*2, 1024**2)
-		return "".join(l)
-
-	def readline(self, limit=-1):
-		data = ""
-		i = self._rbuf.find('\n')
-		while i < 0 and not (0 < limit <= len(self._rbuf)):
-			new = self._sock.recv(self._rbufsize)
-			if not new: break
-			i = new.find('\n')
-			if i >= 0: i = i + len(self._rbuf)
-			self._rbuf = self._rbuf + new
-		if i < 0: i = len(self._rbuf)
-		else: i = i+1
-		if 0 <= limit < len(self._rbuf): i = limit
-		data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
-		return data
-
-	def readlines(self):
-		list = []
-		while 1:
-			line = self.readline()
-			if not line: break
-			list.append(line)
-		return list
-
-
-# WSA error codes
-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."
diff --git a/Lib/socket.py b/Lib/socket.py
new file mode 100644
index 0000000000..3cc8d91187
--- /dev/null
+++ b/Lib/socket.py
@@ -0,0 +1,237 @@
+# 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.
+On other systems, it only supports IP.
+
+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)
+
+ [*] 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.
+"""
+
+from _socket import *
+
+import os, sys
+
+if (sys.platform.lower().startswith("win")
+    or os.uname()[0] == "BeOS"):
+
+    # be sure this happens only once, even in the face of reload():
+    try:
+        _realsocketcall
+    except NameError:
+        _realsocketcall = socket
+
+    def socket(family, type, proto=0):
+        return _socketobject(_realsocketcall(family, type, proto))
+
+
+# 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."
+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()
+    if len(name) == 0:
+        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.
+#
+
+class _socketobject:
+
+    def __init__(self, sock):
+        self._sock = sock
+
+    def close(self):
+        self._sock = 0
+
+    def __del__(self):
+        self.close()
+
+    def accept(self):
+        sock, addr = self._sock.accept()
+        return _socketobject(sock), addr
+
+    def dup(self):
+        return _socketobject(self._sock)
+
+    def makefile(self, mode='r', bufsize=-1):
+        return _fileobject(self._sock, mode, bufsize)
+
+    _s = "def %s(self, *args): return apply(self._sock.%s, args)\n\n"
+    for _m in ('bind', 'connect', 'connect_ex', 'fileno', 'listen',
+               'getpeername', 'getsockname',
+               'getsockopt', 'setsockopt',
+               'recv', 'recvfrom', 'send', 'sendto',
+               'setblocking',
+               'shutdown'):
+        exec _s % (_m, _m)
+
+
+class _fileobject:
+
+    def __init__(self, sock, mode, bufsize):
+        self._sock = sock
+        self._mode = mode
+        if bufsize < 0:
+            bufsize = 512
+        self._rbufsize = max(1, bufsize)
+        self._wbufsize = bufsize
+        self._wbuf = self._rbuf = ""
+
+    def close(self):
+        try:
+            if self._sock:
+                self.flush()
+        finally:
+            self._sock = 0
+
+    def __del__(self):
+        self.close()
+
+    def flush(self):
+        if self._wbuf:
+            self._sock.send(self._wbuf)
+            self._wbuf = ""
+
+    def fileno(self):
+        return self._sock.fileno()
+
+    def write(self, data):
+        self._wbuf = self._wbuf + data
+        if self._wbufsize == 1:
+            if '\n' in data:
+                self.flush()
+        else:
+            if len(self._wbuf) >= self._wbufsize:
+                self.flush()
+
+    def writelines(self, list):
+        filter(self._sock.send, list)
+        self.flush()
+
+    def read(self, n=-1):
+        if n >= 0:
+            k = len(self._rbuf)
+            if n <= k:
+                data = self._rbuf[:n]
+                self._rbuf = self._rbuf[n:]
+                return data
+            n = n - k
+            L = [self._rbuf]
+            self._rbuf = ""
+            while n > 0:
+                new = self._sock.recv(max(n, self._rbufsize))
+                if not new: break
+                k = len(new)
+                if k > n:
+                    L.append(new[:n])
+                    self._rbuf = new[n:]
+                    break
+                L.append(new)
+                n = n - k
+            return "".join(L)
+        k = max(512, self._rbufsize)
+        L = [self._rbuf]
+        self._rbuf = ""
+        while 1:
+            new = self._sock.recv(k)
+            if not new: break
+            L.append(new)
+            k = min(k*2, 1024**2)
+        return "".join(L)
+
+    def readline(self, limit=-1):
+        data = ""
+        i = self._rbuf.find('\n')
+        while i < 0 and not (0 < limit <= len(self._rbuf)):
+            new = self._sock.recv(self._rbufsize)
+            if not new: break
+            i = new.find('\n')
+            if i >= 0: i = i + len(self._rbuf)
+            self._rbuf = self._rbuf + new
+        if i < 0: i = len(self._rbuf)
+        else: i = i+1
+        if 0 <= limit < len(self._rbuf): i = limit
+        data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
+        return data
+
+    def readlines(self):
+        list = []
+        while 1:
+            line = self.readline()
+            if not line: break
+            list.append(line)
+        return list