--- /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()
++