| 2012/02/27 - Operations on haproxy buffers - w@1wt.eu |
| |
| |
| 1) Definitions |
| -------------- |
| |
| A buffer is a unidirectional storage between two stream interfaces which are |
| most often composed of a socket file descriptor. This storage is fixed sized |
| and circular, which means that once data reach the end of the buffer, it loops |
| back at the beginning of the buffer : |
| |
| |
| Representation of a non-wrapping buffer |
| --------------------------------------- |
| |
| |
| beginning end |
| | -------- length --------> | |
| V V |
| +-------------------------------------------+ |
| | <--------------- size ----------------> | |
| +-------------------------------------------+ |
| |
| |
| Representation of a wrapping buffer |
| ----------------------------------- |
| |
| end beginning |
| +------> | | -------------+ |
| | V V | |
| | +-------------------------------------------+ | |
| | | <--------------- size ----------------> | | |
| | +-------------------------------------------+ | |
| | | |
| +--------------------- length -----------------------+ |
| |
| |
| Buffers are read by two entities : |
| - stream interfaces |
| - analysers |
| |
| Buffers are filled by two entities : |
| - stream interfaces |
| - hijackers |
| |
| A stream interface writes at the input of a buffer and reads at its output. An |
| analyser has to parse incoming buffer contents, so it reads the input. It does |
| not really write the output though it may change the buffer's contents at the |
| input, possibly causing data moves. A hijacker it able to write at the output |
| of a buffer. Hijackers are not used anymore at the moment though error outputs |
| still work the same way. |
| |
| Buffers are referenced in the session. Each session has two buffers which |
| interconnect the two stream interfaces. One buffer is called the request |
| buffer, it sees traffic flowing from the client to the server. The other buffer |
| is the response buffer, it sees traffic flowing from the server to the client. |
| |
| By convention, sessions are represented as 2 buffers one on top of the other, |
| and with 2 stream interfaces connected to the two buffers. The client connects |
| to the left stream interface (which then acts as a server), and the right |
| stream interface (which acts as a client) connects to the server. The data |
| circulate clockwise, so the upper buffer is the request buffer and the lower |
| buffer is the response buffer : |
| |
| ,------------------------. |
| ,-----> | request buffer | ------. |
| from ,--./ `------------------------' \,--. to |
| client ( ) ( ) server |
| `--' ,------------------------. /`--' |
| ^------- | response buffer | <-----' |
| `------------------------' |
| |
| 2) Operations |
| ------------- |
| |
| Socket-based stream interfaces write to buffers directly from the I/O layer |
| without relying on any specific function. |
| |
| Function-based stream interfaces do use a number of non-uniform functions to |
| read from the buffer's output and to write to the buffer's input. More suited |
| names could be : |
| |
| int buffer_output_peek_at(buf, ofs, ptr, size); |
| int buffer_output_peek(buf, ptr, size); |
| int buffer_output_read(buf, ptr, size); |
| int buffer_output_skip(buf, size); |
| int buffer_input_write(buf, ptr, size); |
| |
| Right now some stream interfaces use the following functions which also happen |
| to automatically schedule the response for automatic forward : |
| |
| buffer_put_block() [peers] |
| buffer_put_chunk() -> buffer_put_block() |
| buffer_feed_chunk() -> buffer_put_chunk() -> buffer_put_block() [dumpstats] |
| buffer_feed() -> buffer_put_string() -> buffer_put_block() [dumpstats] |
| |
| |
| The following stream-interface oriented functions are not used : |
| |
| buffer_get_char() |
| buffer_write_chunk() |
| |
| |
| Analysers read data from the buffers' input, and may sometimes write data |
| there too (or trim data). More suited names could be : |
| |
| int buffer_input_peek_at(buf, ofs, ptr, size); |
| int buffer_input_truncate_at(buf, ofs); |
| int buffer_input_peek(buf, ptr, size); |
| int buffer_input_read(buf, ptr, size); |
| int buffer_input_skip(buf, size); |
| int buffer_input_cut(buf, size); |
| int buffer_input_truncate(buf); |
| |
| |
| Functions that are available and need to be renamed : |
| - buffer_skip : buffer_output_skip |
| - buffer_ignore : buffer_input_skip ? => not exactly, more like |
| buffer_output_skip() without affecting sendmax ! |
| - buffer_cut_tail : deletes all pending data after sendmax. |
| -> buffer_input_truncate(). Used by si_retnclose() only. |
| - buffer_contig_data : buffer_output_contig_data |
| - buffer_pending : buffer_input_pending_data |
| - buffer_contig_space : buffer_input_contig_space |
| |
| |
| It looks like buf->lr could be removed and be stored in the HTTP message struct |
| since it's only used at the HTTP level. |