|
1 --- Python-2.6.4/Lib/smtpd.py Thu Aug 4 09:36:51 2011 |
|
2 +++ Python-2.6.4/Lib/new.smtpd.py Thu Aug 4 09:51:49 2011 |
|
3 @@ -121,7 +121,15 @@ |
|
4 self.__rcpttos = [] |
|
5 self.__data = '' |
|
6 self.__fqdn = socket.getfqdn() |
|
7 - self.__peer = conn.getpeername() |
|
8 + try: |
|
9 + self.__peer = conn.getpeername() |
|
10 + except socket.error as err: |
|
11 + # a race condition may occur if the other end is closing |
|
12 + # before we can get the peername |
|
13 + self.close() |
|
14 + if err.args[0] != errno.ENOTCONN: |
|
15 + raise |
|
16 + return |
|
17 print >> DEBUGSTREAM, 'Peer:', repr(self.__peer) |
|
18 self.push('220 %s %s' % (self.__fqdn, __version__)) |
|
19 self.set_terminator('\r\n') |
|
20 @@ -285,9 +293,11 @@ |
|
21 localaddr, remoteaddr) |
|
22 |
|
23 def handle_accept(self): |
|
24 - conn, addr = self.accept() |
|
25 - print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr) |
|
26 - channel = SMTPChannel(self, conn, addr) |
|
27 + pair = self.accept() |
|
28 + if pair is not None: |
|
29 + conn, addr = pair |
|
30 + print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr) |
|
31 + channel = SMTPChannel(self, conn, addr) |
|
32 |
|
33 # API for "doing something useful with the message" |
|
34 def process_message(self, peer, mailfrom, rcpttos, data): |
|
35 --- Python-2.6.4/Lib/asyncore.py Wed Apr 15 16:00:41 2009 |
|
36 +++ Python-2.6.4/Lib/new.asyncore.py Thu Aug 4 09:55:22 2011 |
|
37 @@ -340,12 +340,15 @@ |
|
38 # XXX can return either an address pair or None |
|
39 try: |
|
40 conn, addr = self.socket.accept() |
|
41 - return conn, addr |
|
42 - except socket.error, why: |
|
43 - if why.args[0] == EWOULDBLOCK: |
|
44 - pass |
|
45 + except TypeError: |
|
46 + return None |
|
47 + except socket.error as why: |
|
48 + if why.args[0] in (EWOULDBLOCK, ECONNABORTED): |
|
49 + return None |
|
50 else: |
|
51 raise |
|
52 + else: |
|
53 + return conn, addr |
|
54 |
|
55 def send(self, data): |
|
56 try: |
|
57 --- Python-2.6.4/Doc/library/asyncore.rst Wed Apr 15 16:00:41 2009 |
|
58 +++ Python-2.6.4/Doc/library/new.asyncore.rst Thu Aug 4 10:05:40 2011 |
|
59 @@ -210,10 +210,13 @@ |
|
60 .. method:: accept() |
|
61 |
|
62 Accept a connection. The socket must be bound to an address and listening |
|
63 - for connections. The return value is a pair ``(conn, address)`` where |
|
64 - *conn* is a *new* socket object usable to send and receive data on the |
|
65 - connection, and *address* is the address bound to the socket on the other |
|
66 - end of the connection. |
|
67 + for connections. The return value can be either ``None`` or a pair |
|
68 + ``(conn, address)`` where *conn* is a *new* socket object usable to send |
|
69 + and receive data on the connection, and *address* is the address bound to |
|
70 + the socket on the other end of the connection. |
|
71 + When ``None`` is returned it means the connection didn't take place, in |
|
72 + which case the server should just ignore this event and keep listening |
|
73 + for further incoming connections. |
|
74 |
|
75 |
|
76 .. method:: close() |
|
77 @@ -223,6 +226,12 @@ |
|
78 flushed). Sockets are automatically closed when they are |
|
79 garbage-collected. |
|
80 |
|
81 +.. class:: dispatcher_with_send() |
|
82 + |
|
83 + A :class:`dispatcher` subclass which adds simple buffered output capability, |
|
84 + useful for simple clients. For more sophisticated usage use |
|
85 + :class:`asynchat.async_chat`. |
|
86 + |
|
87 .. class:: file_dispatcher() |
|
88 |
|
89 A file_dispatcher takes a file descriptor or file object along with an |
|
90 @@ -239,7 +248,7 @@ |
|
91 socket for use by the :class:`file_dispatcher` class. Availability: UNIX. |
|
92 |
|
93 |
|
94 -.. _asyncore-example: |
|
95 +.. _asyncore-example-1: |
|
96 |
|
97 asyncore Example basic HTTP client |
|
98 ---------------------------------- |
|
99 @@ -249,7 +258,7 @@ |
|
100 |
|
101 import asyncore, socket |
|
102 |
|
103 - class http_client(asyncore.dispatcher): |
|
104 + class HTTPClient(asyncore.dispatcher): |
|
105 |
|
106 def __init__(self, host, path): |
|
107 asyncore.dispatcher.__init__(self) |
|
108 @@ -273,6 +282,45 @@ |
|
109 sent = self.send(self.buffer) |
|
110 self.buffer = self.buffer[sent:] |
|
111 |
|
112 - c = http_client('www.python.org', '/') |
|
113 |
|
114 + client = HTTPClient('www.python.org', '/') |
|
115 asyncore.loop() |
|
116 + |
|
117 +.. _asyncore-example-2: |
|
118 + |
|
119 +asyncore Example basic echo server |
|
120 +---------------------------------- |
|
121 + |
|
122 +Here is abasic echo server that uses the :class:`dispatcher` class to accept |
|
123 +connections and dispatches the incoming connections to a handler:: |
|
124 + |
|
125 + import asyncore |
|
126 + import socket |
|
127 + |
|
128 + class EchoHandler(asyncore.dispatcher_with_send): |
|
129 + |
|
130 + def handle_read(self): |
|
131 + data = self.recv(8192) |
|
132 + self.send(data) |
|
133 + |
|
134 + class EchoServer(asyncore.dispatcher): |
|
135 + |
|
136 + def __init__(self, host, port): |
|
137 + asyncore.dispatcher.__init__(self) |
|
138 + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
|
139 + self.set_reuse_addr() |
|
140 + self.bind((host, port)) |
|
141 + self.listen(5) |
|
142 + |
|
143 + def handle_accept(self): |
|
144 + pair = self.accept() |
|
145 + if pair is None: |
|
146 + pass |
|
147 + else: |
|
148 + sock, addr = pair |
|
149 + print 'Incoming connection from %s' % repr(addr) |
|
150 + handler = EchoHandler(sock) |
|
151 + |
|
152 + server = EchoServer('localhost', 8080) |
|
153 + asyncore.loop() |
|
154 + |