components/python/python26/patches/Python26-23-none-on-connect.patch
changeset 470 fda4329d05f4
child 841 1a62cefa636d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/python26/patches/Python26-23-none-on-connect.patch	Fri Aug 12 12:26:15 2011 -0700
@@ -0,0 +1,154 @@
+--- Python-2.6.4/Lib/smtpd.py	Thu Aug  4 09:36:51 2011
++++ Python-2.6.4/Lib/new.smtpd.py	Thu Aug  4 09:51:49 2011
+@@ -121,7 +121,15 @@
+         self.__rcpttos = []
+         self.__data = ''
+         self.__fqdn = socket.getfqdn()
+-        self.__peer = conn.getpeername()
++        try:
++            self.__peer = conn.getpeername()
++        except socket.error as err:
++            # a race condition  may occur if the other end is closing
++            # before we can get the peername
++            self.close()
++            if err.args[0] != errno.ENOTCONN:
++                raise
++            return
+         print >> DEBUGSTREAM, 'Peer:', repr(self.__peer)
+         self.push('220 %s %s' % (self.__fqdn, __version__))
+         self.set_terminator('\r\n')
+@@ -285,9 +293,11 @@
+             localaddr, remoteaddr)
+ 
+     def handle_accept(self):
+-        conn, addr = self.accept()
+-        print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
+-        channel = SMTPChannel(self, conn, addr)
++        pair = self.accept()
++        if pair is not None:
++            conn, addr = pair
++            print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
++            channel = SMTPChannel(self, conn, addr)
+ 
+     # API for "doing something useful with the message"
+     def process_message(self, peer, mailfrom, rcpttos, data):
+--- Python-2.6.4/Lib/asyncore.py	Wed Apr 15 16:00:41 2009
++++ Python-2.6.4/Lib/new.asyncore.py	Thu Aug  4 09:55:22 2011
+@@ -340,12 +340,15 @@
+         # XXX can return either an address pair or None
+         try:
+             conn, addr = self.socket.accept()
+-            return conn, addr
+-        except socket.error, why:
+-            if why.args[0] == EWOULDBLOCK:
+-                pass
++        except TypeError:
++            return None
++        except socket.error as why:
++            if why.args[0] in (EWOULDBLOCK, ECONNABORTED):
++                return None
+             else:
+                 raise
++        else:
++            return conn, addr
+ 
+     def send(self, data):
+         try:
+--- Python-2.6.4/Doc/library/asyncore.rst	Wed Apr 15 16:00:41 2009
++++ Python-2.6.4/Doc/library/new.asyncore.rst	Thu Aug  4 10:05:40 2011
+@@ -210,10 +210,13 @@
+    .. method:: accept()
+ 
+       Accept a connection.  The socket must be bound to an address and listening
+-      for connections.  The return value is a pair ``(conn, address)`` where
+-      *conn* is a *new* socket object usable to send and receive data on the
+-      connection, and *address* is the address bound to the socket on the other
+-      end of the connection.
++      for connections.  The return value can be either ``None`` or a pair
++      ``(conn, address)`` where *conn* is a *new* socket object usable to send
++      and receive data on the connection, and *address* is the address bound to
++      the socket on the other end of the connection.
++      When ``None`` is returned it means the connection didn't take place, in
++      which case the server should just ignore this event and keep listening
++      for further incoming connections.
+ 
+ 
+    .. method:: close()
+@@ -223,6 +226,12 @@
+       flushed).  Sockets are automatically closed when they are
+       garbage-collected.
+ 
++.. class:: dispatcher_with_send()
++
++   A :class:`dispatcher` subclass which adds simple buffered output capability,
++   useful for simple clients. For more sophisticated usage use
++   :class:`asynchat.async_chat`.
++
+ .. class:: file_dispatcher()
+ 
+    A file_dispatcher takes a file descriptor or file object along with an
+@@ -239,7 +248,7 @@
+    socket for use by the :class:`file_dispatcher` class.  Availability: UNIX.
+ 
+ 
+-.. _asyncore-example:
++.. _asyncore-example-1:
+ 
+ asyncore Example basic HTTP client
+ ----------------------------------
+@@ -249,7 +258,7 @@
+ 
+    import asyncore, socket
+ 
+-   class http_client(asyncore.dispatcher):
++   class HTTPClient(asyncore.dispatcher):
+ 
+        def __init__(self, host, path):
+            asyncore.dispatcher.__init__(self)
+@@ -273,6 +282,45 @@
+            sent = self.send(self.buffer)
+            self.buffer = self.buffer[sent:]
+ 
+-   c = http_client('www.python.org', '/')
+ 
++   client = HTTPClient('www.python.org', '/')
+    asyncore.loop()
++
++.. _asyncore-example-2:
++
++asyncore Example basic echo server
++----------------------------------
++
++Here is abasic echo server that uses the :class:`dispatcher` class to accept
++connections and dispatches the incoming connections to a handler::
++
++    import asyncore
++    import socket
++
++    class EchoHandler(asyncore.dispatcher_with_send):
++
++        def handle_read(self):
++            data = self.recv(8192)
++            self.send(data)
++
++    class EchoServer(asyncore.dispatcher):
++
++        def __init__(self, host, port):
++            asyncore.dispatcher.__init__(self)
++            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
++            self.set_reuse_addr()
++            self.bind((host, port))
++            self.listen(5)
++
++        def handle_accept(self):
++            pair = self.accept()
++            if pair is None:
++                pass
++            else:
++                sock, addr = pair
++                print 'Incoming connection from %s' % repr(addr)
++                handler = EchoHandler(sock)
++
++    server = EchoServer('localhost', 8080)
++    asyncore.loop()
++