blob: ee00f1c8f05d6598649d5757e05b2886103ac671 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Buffer management functions.
3 *
Willy Tarreaue09e0ce2007-03-18 16:31:29 +01004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010013#include <stdarg.h>
14#include <stdio.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020015#include <string.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020016
17#include <common/config.h>
Willy Tarreau7341d942007-05-13 19:56:02 +020018#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020019#include <proto/buffers.h>
Willy Tarreau27a674e2009-08-17 07:23:33 +020020#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
Willy Tarreau7341d942007-05-13 19:56:02 +020022struct pool_head *pool2_buffer;
23
24
25/* perform minimal intializations, report 0 in case of error, 1 if OK. */
26int init_buffer()
27{
Willy Tarreau27a674e2009-08-17 07:23:33 +020028 pool2_buffer = create_pool("buffer", sizeof(struct buffer) + global.tune.bufsize, MEM_F_SHARED);
Willy Tarreau7341d942007-05-13 19:56:02 +020029 return pool2_buffer != NULL;
30}
31
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020033/* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
Willy Tarreau078e2942009-08-18 07:19:39 +020034 * success, -2 if the message is larger than the buffer size, or the number of
35 * bytes available otherwise. The send limit is automatically adjusted with the
36 * amount of data written. FIXME-20060521: handle unaligned data.
Willy Tarreaubaaee002006-06-26 02:48:02 +020037 */
38int buffer_write(struct buffer *buf, const char *msg, int len)
39{
40 int max;
41
Willy Tarreauaeac3192009-08-31 08:09:57 +020042 if (len == 0)
43 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
Willy Tarreau078e2942009-08-18 07:19:39 +020045 if (len > buf->size) {
46 /* we can't write this chunk and will never be able to, because
47 * it is larger than the buffer. This must be reported as an
48 * error. Then we return -2 so that writers that don't care can
49 * ignore it and go on, and others can check for this value.
50 */
51 return -2;
52 }
53
Willy Tarreauaeac3192009-08-31 08:09:57 +020054 max = buffer_realign(buf);
55
Willy Tarreaubaaee002006-06-26 02:48:02 +020056 if (len > max)
57 return max;
58
59 memcpy(buf->r, msg, len);
60 buf->l += len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010061 buf->send_max += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020062 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010063 buf->total += len;
Willy Tarreaua07a34e2009-08-16 23:27:46 +020064 if (buf->r == buf->data + buf->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +020065 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020066
Willy Tarreauba0b63d2009-09-20 08:09:44 +020067 buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
Willy Tarreau03d60bb2009-01-09 11:13:00 +010068 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +020069 buf->flags |= BF_FULL;
70
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020071 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020072}
73
Willy Tarreauaeac3192009-08-31 08:09:57 +020074/* Try to write string <str> into buffer <buf> after length controls. This
75 * is the equivalent of buffer_write() except that to_forward and send_max
76 * are updated and that max_len is respected. Returns -1 in case of success,
Willy Tarreau078e2942009-08-18 07:19:39 +020077 * -2 if it is larger than the buffer size, or the number of bytes available
Willy Tarreauaeac3192009-08-31 08:09:57 +020078 * otherwise. The send limit is automatically adjusted with the amount of data
Willy Tarreau078e2942009-08-18 07:19:39 +020079 * written.
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010080 */
Willy Tarreauaeac3192009-08-31 08:09:57 +020081int buffer_feed(struct buffer *buf, const char *str, int len)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010082{
83 int max;
84
Willy Tarreauaeac3192009-08-31 08:09:57 +020085 if (len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020086 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010087
Willy Tarreauaeac3192009-08-31 08:09:57 +020088 if (len > buf->max_len) {
Willy Tarreau078e2942009-08-18 07:19:39 +020089 /* we can't write this chunk and will never be able to, because
Willy Tarreauaeac3192009-08-31 08:09:57 +020090 * it is larger than the buffer's current max size.
Willy Tarreau078e2942009-08-18 07:19:39 +020091 */
92 return -2;
93 }
94
Willy Tarreauaeac3192009-08-31 08:09:57 +020095 max = buffer_contig_space(buf);
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010096
Willy Tarreauaeac3192009-08-31 08:09:57 +020097 if (len > max)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010098 return max;
99
Willy Tarreauaeac3192009-08-31 08:09:57 +0200100 memcpy(buf->r, str, len);
101 buf->l += len;
102 buf->r += len;
103 buf->total += len;
Willy Tarreau31971e52009-09-20 12:07:52 +0200104 if (buf->to_forward) {
105 unsigned long fwd = len;
106 if (buf->to_forward != BUF_INFINITE_FORWARD) {
107 if (fwd > buf->to_forward)
108 fwd = buf->to_forward;
109 buf->to_forward -= fwd;
110 }
111 buf->send_max += fwd;
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200112 buf->flags &= ~BF_OUT_EMPTY;
Willy Tarreauaeac3192009-08-31 08:09:57 +0200113 }
114
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200115 if (buf->r == buf->data + buf->size)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100116 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200117
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200118 buf->flags &= ~BF_FULL;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100119 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200120 buf->flags |= BF_FULL;
121
Willy Tarreaufb0e9202009-09-23 23:47:55 +0200122 /* notify that some data was read from the SI into the buffer */
123 buf->flags |= BF_READ_PARTIAL;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200124 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100125}
126
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200127/* Get one text line out of a buffer from a stream interface.
128 * Return values :
129 * >0 : number of bytes read. Includes the \n if present before len or end.
130 * =0 : no '\n' before end found. <buf> is undefined.
131 * <0 : no more bytes readable + shutdown set.
132 * The buffer status is not changed. The caller must call buffer_skip() to
133 * update it. The '\n' is waited for as long as neither the buffer nor the
134 * output are full. If either of them is full, the string may be returned
135 * as is, without the '\n'.
136 */
137int buffer_si_peekline(struct buffer *buf, char *str, int len)
138{
139 int ret, max;
140 char *p;
141
142 ret = 0;
143 max = len;
144 if (!buf->send_max) {
145 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
146 ret = -1;
147 goto out;
148 }
149
150 p = buf->w;
151
152 if (max > buf->send_max) {
153 max = buf->send_max;
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200154 str[max-1] = 0;
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200155 }
156 while (max) {
157 *str++ = *p;
158 ret++;
159 max--;
160
161 if (*p == '\n')
162 break;
163 p++;
164 if (p == buf->data + buf->size)
165 p = buf->data;
166 }
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200167 if (ret > 0 && ret < len && ret < buf->send_max &&
168 *(str-1) != '\n' &&
169 !(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)))
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200170 ret = 0;
171 out:
172 if (max)
173 *str = 0;
174 return ret;
175}
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * this function writes the string <str> at position <pos> which must be in buffer <b>,
179 * and moves <end> just after the end of <str>.
180 * <b>'s parameters (l, r, w, h, lr) are recomputed to be valid after the shift.
181 * the shift value (positive or negative) is returned.
182 * If there's no space left, the move is not done.
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200183 * The function does not adjust ->send_max nor BF_OUT_EMPTY because it does not
184 * make sense to use it on data scheduled to be sent.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 *
186 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100187int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188{
189 int delta;
190 int len;
191
192 len = strlen(str);
193 delta = len - (end - pos);
194
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200195 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 return 0; /* no space left */
197
198 /* first, protect the end of the buffer */
199 memmove(end + delta, end, b->data + b->l - end);
200
201 /* now, copy str over pos */
202 memcpy(pos, str,len);
203
204 /* we only move data after the displaced zone */
205 if (b->r > pos) b->r += delta;
206 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 if (b->lr > pos) b->lr += delta;
208 b->l += delta;
209
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200210 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200211 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200212 b->r = b->w = b->lr = b->data;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100213 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200214 b->flags |= BF_FULL;
215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 return delta;
217}
218
219/*
220 * same except that the string length is given, which allows str to be NULL if
Willy Tarreauf890dc92008-12-13 21:12:26 +0100221 * len is 0. The send limit is *not* adjusted.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100223int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 int delta;
226
227 delta = len - (end - pos);
228
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200229 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 return 0; /* no space left */
231
232 if (b->data + b->l < end) {
233 /* The data has been stolen, we could have crashed.
234 * Maybe we should abort() ? */
235 return 0;
236 }
237
238 /* first, protect the end of the buffer */
239 memmove(end + delta, end, b->data + b->l - end);
240
241 /* now, copy str over pos */
242 if (len)
243 memcpy(pos, str, len);
244
245 /* we only move data after the displaced zone */
246 if (b->r > pos) b->r += delta;
247 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248 if (b->lr > pos) b->lr += delta;
249 b->l += delta;
250
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200251 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200252 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200253 b->r = b->w = b->lr = b->data;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100254 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200255 b->flags |= BF_FULL;
256
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257 return delta;
258}
259
260
261/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100262 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
263 * argument informs about the length of string <str> so that we don't have to
264 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
265 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
Willy Tarreauf890dc92008-12-13 21:12:26 +0100266 * some circumstances. The send limit is *not* adjusted.
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100267 *
268 * The number of bytes added is returned on success. 0 is returned on failure.
269 */
270int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
271{
272 int delta;
273
274 delta = len + 2;
275
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200276 if (delta + b->r >= b->data + b->size)
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100277 return 0; /* no space left */
278
279 /* first, protect the end of the buffer */
280 memmove(pos + delta, pos, b->data + b->l - pos);
281
282 /* now, copy str over pos */
283 if (len && str) {
284 memcpy(pos, str, len);
285 pos[len] = '\r';
286 pos[len + 1] = '\n';
287 }
288
289 /* we only move data after the displaced zone */
290 if (b->r > pos) b->r += delta;
291 if (b->w > pos) b->w += delta;
292 if (b->lr > pos) b->lr += delta;
293 b->l += delta;
294
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200295 b->flags &= ~BF_FULL;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100296 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200297 b->flags |= BF_FULL;
298
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100299 return delta;
300}
301
302
303/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100304 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200305 * at most chk->size chars. If the chk->len is over, nothing is added. Returns
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100306 * the new chunk size.
307 */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200308int chunk_printf(struct chunk *chk, const char *fmt, ...)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100309{
310 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200311 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100312
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200313 if (!chk->str || !chk->size)
314 return 0;
315
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100316 va_start(argp, fmt);
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200317 ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp);
318 if (ret >= chk->size - chk->len)
Willy Tarreaudceaa082007-07-25 14:38:45 +0200319 /* do not copy anything in case of truncation */
320 chk->str[chk->len] = 0;
321 else
322 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100323 va_end(argp);
324 return chk->len;
325}
326
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100327/*
328 * Dumps part or all of a buffer.
329 */
330void buffer_dump(FILE *o, struct buffer *b, int from, int to)
331{
332 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100333 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
334 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100335
336 if (!to || to > b->l)
337 to = b->l;
338
339 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
340 for (; from < to; from++) {
341 if ((from & 15) == 0)
342 fprintf(o, " %04x: ", from);
343 fprintf(o, "%02x ", b->data[from]);
344 if ((from & 15) == 7)
345 fprintf(o, "- ");
346 else if (((from & 15) == 15) && (from != to-1))
347 fprintf(o, "\n");
348 }
349 fprintf(o, "\n--\n");
350}
351
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100352
353/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200354 * Local variables:
355 * c-indent-level: 8
356 * c-basic-offset: 8
357 * End:
358 */