blob: e511a05216075180499123bd3198d1be4f5b2e73 [file] [log] [blame]
Georg Brandl116aa622007-08-15 14:28:22 +00001:mod:`asynchat` --- Asynchronous socket command/response handler
2================================================================
3
4.. module:: asynchat
5 :synopsis: Support for asynchronous command/response protocols.
6.. moduleauthor:: Sam Rushing <rushing@nightmare.com>
Josiah Carlson35bf9bf2008-07-07 04:24:24 +00007.. sectionauthor:: Steve Holden <sholden@holdenweb.com>
Georg Brandl116aa622007-08-15 14:28:22 +00008
9
10This module builds on the :mod:`asyncore` infrastructure, simplifying
Georg Brandl9afde1c2007-11-01 20:32:30 +000011asynchronous clients and servers and making it easier to handle protocols
12whose elements are terminated by arbitrary strings, or are of variable length.
Georg Brandl116aa622007-08-15 14:28:22 +000013:mod:`asynchat` defines the abstract class :class:`async_chat` that you
14subclass, providing implementations of the :meth:`collect_incoming_data` and
15:meth:`found_terminator` methods. It uses the same asynchronous loop as
Georg Brandl9afde1c2007-11-01 20:32:30 +000016:mod:`asyncore`, and the two types of channel, :class:`asyncore.dispatcher`
17and :class:`asynchat.async_chat`, can freely be mixed in the channel map.
18Typically an :class:`asyncore.dispatcher` server channel generates new
19:class:`asynchat.async_chat` channel objects as it receives incoming
20connection requests.
Georg Brandl116aa622007-08-15 14:28:22 +000021
22
23.. class:: async_chat()
24
25 This class is an abstract subclass of :class:`asyncore.dispatcher`. To make
26 practical use of the code you must subclass :class:`async_chat`, providing
Georg Brandl9afde1c2007-11-01 20:32:30 +000027 meaningful :meth:`collect_incoming_data` and :meth:`found_terminator`
28 methods.
Georg Brandl116aa622007-08-15 14:28:22 +000029 The :class:`asyncore.dispatcher` methods can be used, although not all make
30 sense in a message/response context.
31
Georg Brandl9afde1c2007-11-01 20:32:30 +000032 Like :class:`asyncore.dispatcher`, :class:`async_chat` defines a set of
33 events that are generated by an analysis of socket conditions after a
34 :cfunc:`select` call. Once the polling loop has been started the
35 :class:`async_chat` object's methods are called by the event-processing
36 framework with no action on the part of the programmer.
Georg Brandl116aa622007-08-15 14:28:22 +000037
Georg Brandl9afde1c2007-11-01 20:32:30 +000038 Two class attributes can be modified, to improve performance, or possibly
39 even to conserve memory.
40
41
42 .. data:: ac_in_buffer_size
43
44 The asynchronous input buffer size (default ``4096``).
45
46
47 .. data:: ac_out_buffer_size
48
49 The asynchronous output buffer size (default ``4096``).
50
51 Unlike :class:`asyncore.dispatcher`, :class:`async_chat` allows you to
52 define a first-in-first-out queue (fifo) of *producers*. A producer need
53 have only one method, :meth:`more`, which should return data to be
54 transmitted on the channel.
Georg Brandl116aa622007-08-15 14:28:22 +000055 The producer indicates exhaustion (*i.e.* that it contains no more data) by
56 having its :meth:`more` method return the empty string. At this point the
Georg Brandl9afde1c2007-11-01 20:32:30 +000057 :class:`async_chat` object removes the producer from the fifo and starts
58 using the next producer, if any. When the producer fifo is empty the
Georg Brandl116aa622007-08-15 14:28:22 +000059 :meth:`handle_write` method does nothing. You use the channel object's
Georg Brandl9afde1c2007-11-01 20:32:30 +000060 :meth:`set_terminator` method to describe how to recognize the end of, or
61 an important breakpoint in, an incoming transmission from the remote
62 endpoint.
Georg Brandl116aa622007-08-15 14:28:22 +000063
64 To build a functioning :class:`async_chat` subclass your input methods
Georg Brandl9afde1c2007-11-01 20:32:30 +000065 :meth:`collect_incoming_data` and :meth:`found_terminator` must handle the
66 data that the channel receives asynchronously. The methods are described
67 below.
Georg Brandl116aa622007-08-15 14:28:22 +000068
69
70.. method:: async_chat.close_when_done()
71
Georg Brandl9afde1c2007-11-01 20:32:30 +000072 Pushes a ``None`` on to the producer fifo. When this producer is popped off
73 the fifo it causes the channel to be closed.
Georg Brandl116aa622007-08-15 14:28:22 +000074
75
76.. method:: async_chat.collect_incoming_data(data)
77
Georg Brandl9afde1c2007-11-01 20:32:30 +000078 Called with *data* holding an arbitrary amount of received data. The
79 default method, which must be overridden, raises a
80 :exc:`NotImplementedError` exception.
Georg Brandl116aa622007-08-15 14:28:22 +000081
82
Josiah Carlsond74900e2008-07-07 04:15:08 +000083.. method:: async_chat._collect_incoming_data(data)
84
85 Sample implementation of a data collection rutine to be used in conjunction
86 with :meth:`_get_data` in a user-specified :meth:`found_terminator`.
87
88
Georg Brandl116aa622007-08-15 14:28:22 +000089.. method:: async_chat.discard_buffers()
90
Georg Brandl9afde1c2007-11-01 20:32:30 +000091 In emergencies this method will discard any data held in the input and/or
92 output buffers and the producer fifo.
Georg Brandl116aa622007-08-15 14:28:22 +000093
94
95.. method:: async_chat.found_terminator()
96
Georg Brandl9afde1c2007-11-01 20:32:30 +000097 Called when the incoming data stream matches the termination condition set
98 by :meth:`set_terminator`. The default method, which must be overridden,
99 raises a :exc:`NotImplementedError` exception. The buffered input data
100 should be available via an instance attribute.
Georg Brandl116aa622007-08-15 14:28:22 +0000101
102
Josiah Carlsond74900e2008-07-07 04:15:08 +0000103.. method:: async_chat._get_data()
104
105 Will return and clear the data received with the sample
106 :meth:`_collect_incoming_data` implementation.
107
108
Georg Brandl116aa622007-08-15 14:28:22 +0000109.. method:: async_chat.get_terminator()
110
111 Returns the current terminator for the channel.
112
113
114.. method:: async_chat.handle_close()
115
116 Called when the channel is closed. The default method silently closes the
117 channel's socket.
118
119
120.. method:: async_chat.handle_read()
121
Georg Brandl9afde1c2007-11-01 20:32:30 +0000122 Called when a read event fires on the channel's socket in the asynchronous
123 loop. The default method checks for the termination condition established
124 by :meth:`set_terminator`, which can be either the appearance of a
125 particular string in the input stream or the receipt of a particular number
126 of characters. When the terminator is found, :meth:`handle_read` calls the
127 :meth:`found_terminator` method after calling :meth:`collect_incoming_data`
128 with any data preceding the terminating condition.
Georg Brandl116aa622007-08-15 14:28:22 +0000129
130
131.. method:: async_chat.handle_write()
132
Georg Brandl9afde1c2007-11-01 20:32:30 +0000133 Called when the application may write data to the channel. The default
134 method calls the :meth:`initiate_send` method, which in turn will call
135 :meth:`refill_buffer` to collect data from the producer fifo associated
136 with the channel.
Georg Brandl116aa622007-08-15 14:28:22 +0000137
138
139.. method:: async_chat.push(data)
140
Georg Brandl9afde1c2007-11-01 20:32:30 +0000141 Creates a :class:`simple_producer` object (*see below*) containing the data
142 and pushes it on to the channel's ``producer_fifo`` to ensure its
143 transmission. This is all you need to do to have the channel write the
144 data out to the network, although it is possible to use your own producers
145 in more complex schemes to implement encryption and chunking, for example.
Georg Brandl116aa622007-08-15 14:28:22 +0000146
147
148.. method:: async_chat.push_with_producer(producer)
149
Georg Brandl9afde1c2007-11-01 20:32:30 +0000150 Takes a producer object and adds it to the producer fifo associated with
151 the channel. When all currently-pushed producers have been exhausted the
152 channel will consume this producer's data by calling its :meth:`more`
153 method and send the data to the remote endpoint.
Georg Brandl116aa622007-08-15 14:28:22 +0000154
155
156.. method:: async_chat.readable()
157
Georg Brandl9afde1c2007-11-01 20:32:30 +0000158 Should return ``True`` for the channel to be included in the set of
159 channels tested by the :cfunc:`select` loop for readability.
Georg Brandl116aa622007-08-15 14:28:22 +0000160
161
162.. method:: async_chat.refill_buffer()
163
Georg Brandl9afde1c2007-11-01 20:32:30 +0000164 Refills the output buffer by calling the :meth:`more` method of the
165 producer at the head of the fifo. If it is exhausted then the producer is
166 popped off the fifo and the next producer is activated. If the current
167 producer is, or becomes, ``None`` then the channel is closed.
Georg Brandl116aa622007-08-15 14:28:22 +0000168
169
170.. method:: async_chat.set_terminator(term)
171
Georg Brandl9afde1c2007-11-01 20:32:30 +0000172 Sets the terminating condition to be recognized on the channel. ``term``
173 may be any of three types of value, corresponding to three different ways
174 to handle incoming protocol data.
Georg Brandl116aa622007-08-15 14:28:22 +0000175
176 +-----------+---------------------------------------------+
177 | term | Description |
178 +===========+=============================================+
179 | *string* | Will call :meth:`found_terminator` when the |
180 | | string is found in the input stream |
181 +-----------+---------------------------------------------+
182 | *integer* | Will call :meth:`found_terminator` when the |
183 | | indicated number of characters have been |
184 | | received |
185 +-----------+---------------------------------------------+
186 | ``None`` | The channel continues to collect data |
187 | | forever |
188 +-----------+---------------------------------------------+
189
Georg Brandl9afde1c2007-11-01 20:32:30 +0000190 Note that any data following the terminator will be available for reading
191 by the channel after :meth:`found_terminator` is called.
Georg Brandl116aa622007-08-15 14:28:22 +0000192
193
194.. method:: async_chat.writable()
195
196 Should return ``True`` as long as items remain on the producer fifo, or the
197 channel is connected and the channel's output buffer is non-empty.
198
199
200asynchat - Auxiliary Classes and Functions
201------------------------------------------
202
203
Georg Brandlb868a662009-04-02 02:56:10 +0000204.. class:: simple_producer(data, buffer_size=512)
Georg Brandl116aa622007-08-15 14:28:22 +0000205
Georg Brandl9afde1c2007-11-01 20:32:30 +0000206 A :class:`simple_producer` takes a chunk of data and an optional buffer
207 size. Repeated calls to its :meth:`more` method yield successive chunks of
208 the data no larger than *buffer_size*.
Georg Brandl116aa622007-08-15 14:28:22 +0000209
210
Benjamin Petersone41251e2008-04-25 01:59:09 +0000211 .. method:: more()
Georg Brandl116aa622007-08-15 14:28:22 +0000212
Benjamin Petersone41251e2008-04-25 01:59:09 +0000213 Produces the next chunk of information from the producer, or returns the
214 empty string.
Georg Brandl116aa622007-08-15 14:28:22 +0000215
216
Georg Brandlb868a662009-04-02 02:56:10 +0000217.. class:: fifo(list=None)
Georg Brandl116aa622007-08-15 14:28:22 +0000218
Georg Brandl9afde1c2007-11-01 20:32:30 +0000219 Each channel maintains a :class:`fifo` holding data which has been pushed
220 by the application but not yet popped for writing to the channel. A
221 :class:`fifo` is a list used to hold data and/or producers until they are
222 required. If the *list* argument is provided then it should contain
223 producers or data items to be written to the channel.
Georg Brandl116aa622007-08-15 14:28:22 +0000224
225
Benjamin Petersone41251e2008-04-25 01:59:09 +0000226 .. method:: is_empty()
Georg Brandl116aa622007-08-15 14:28:22 +0000227
Benjamin Petersone41251e2008-04-25 01:59:09 +0000228 Returns ``True`` if and only if the fifo is empty.
Georg Brandl116aa622007-08-15 14:28:22 +0000229
230
Benjamin Petersone41251e2008-04-25 01:59:09 +0000231 .. method:: first()
Georg Brandl116aa622007-08-15 14:28:22 +0000232
Benjamin Petersone41251e2008-04-25 01:59:09 +0000233 Returns the least-recently :meth:`push`\ ed item from the fifo.
Georg Brandl116aa622007-08-15 14:28:22 +0000234
235
Benjamin Petersone41251e2008-04-25 01:59:09 +0000236 .. method:: push(data)
Georg Brandl116aa622007-08-15 14:28:22 +0000237
Benjamin Petersone41251e2008-04-25 01:59:09 +0000238 Adds the given data (which may be a string or a producer object) to the
239 producer fifo.
Georg Brandl116aa622007-08-15 14:28:22 +0000240
241
Benjamin Petersone41251e2008-04-25 01:59:09 +0000242 .. method:: pop()
Georg Brandl116aa622007-08-15 14:28:22 +0000243
Benjamin Petersone41251e2008-04-25 01:59:09 +0000244 If the fifo is not empty, returns ``True, first()``, deleting the popped
245 item. Returns ``False, None`` for an empty fifo.
Georg Brandl116aa622007-08-15 14:28:22 +0000246
247The :mod:`asynchat` module also defines one utility function, which may be of
248use in network and textual analysis operations.
249
250
251.. function:: find_prefix_at_end(haystack, needle)
252
Georg Brandl9afde1c2007-11-01 20:32:30 +0000253 Returns ``True`` if string *haystack* ends with any non-empty prefix of
254 string *needle*.
Georg Brandl116aa622007-08-15 14:28:22 +0000255
256
257.. _asynchat-example:
258
259asynchat Example
260----------------
261
262The following partial example shows how HTTP requests can be read with
Georg Brandl9afde1c2007-11-01 20:32:30 +0000263:class:`async_chat`. A web server might create an
264:class:`http_request_handler` object for each incoming client connection.
265Notice that initially the channel terminator is set to match the blank line at
266the end of the HTTP headers, and a flag indicates that the headers are being
267read.
Georg Brandl116aa622007-08-15 14:28:22 +0000268
Georg Brandl9afde1c2007-11-01 20:32:30 +0000269Once the headers have been read, if the request is of type POST (indicating
270that further data are present in the input stream) then the
271``Content-Length:`` header is used to set a numeric terminator to read the
272right amount of data from the channel.
Georg Brandl116aa622007-08-15 14:28:22 +0000273
274The :meth:`handle_request` method is called once all relevant input has been
Georg Brandl9afde1c2007-11-01 20:32:30 +0000275marshalled, after setting the channel terminator to ``None`` to ensure that
276any extraneous data sent by the web client are ignored. ::
Georg Brandl116aa622007-08-15 14:28:22 +0000277
278 class http_request_handler(asynchat.async_chat):
279
Benjamin Peterson9bc93512008-09-22 22:10:59 +0000280 def __init__(self, sock, addr, sessions, log):
281 asynchat.async_chat.__init__(self, sock=sock)
Georg Brandl116aa622007-08-15 14:28:22 +0000282 self.addr = addr
283 self.sessions = sessions
284 self.ibuffer = []
Josiah Carlson1893ce72008-07-07 04:23:14 +0000285 self.obuffer = b""
286 self.set_terminator(b"\r\n\r\n")
Georg Brandl116aa622007-08-15 14:28:22 +0000287 self.reading_headers = True
288 self.handling = False
289 self.cgi_data = None
290 self.log = log
291
292 def collect_incoming_data(self, data):
293 """Buffer the data"""
294 self.ibuffer.append(data)
295
296 def found_terminator(self):
297 if self.reading_headers:
298 self.reading_headers = False
299 self.parse_headers("".join(self.ibuffer))
300 self.ibuffer = []
Josiah Carlson1893ce72008-07-07 04:23:14 +0000301 if self.op.upper() == b"POST":
Georg Brandl116aa622007-08-15 14:28:22 +0000302 clen = self.headers.getheader("content-length")
303 self.set_terminator(int(clen))
304 else:
305 self.handling = True
306 self.set_terminator(None)
307 self.handle_request()
308 elif not self.handling:
309 self.set_terminator(None) # browsers sometimes over-send
Josiah Carlson1893ce72008-07-07 04:23:14 +0000310 self.cgi_data = parse(self.headers, b"".join(self.ibuffer))
Georg Brandl116aa622007-08-15 14:28:22 +0000311 self.handling = True
312 self.ibuffer = []
313 self.handle_request()