blob: a20f3f499b814c65076e1b6d1a779c62e68b95e6 [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 Tarreauf890dc92008-12-13 21:12:26 +010034 * success, or the number of bytes available otherwise. The send limit is
35 * automatically adjusted with the amount of data written.
Willy Tarreaubaaee002006-06-26 02:48:02 +020036 * FIXME-20060521: handle unaligned data.
37 */
38int buffer_write(struct buffer *buf, const char *msg, int len)
39{
40 int max;
41
42 max = buffer_realign(buf);
43
44 if (len > max)
45 return max;
46
47 memcpy(buf->r, msg, len);
48 buf->l += len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010049 buf->send_max += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020050 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010051 buf->total += len;
Willy Tarreaua07a34e2009-08-16 23:27:46 +020052 if (buf->r == buf->data + buf->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +020053 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020054
Willy Tarreaue393fe22008-08-16 22:18:07 +020055 buf->flags &= ~(BF_EMPTY|BF_FULL);
56 if (buf->l == 0)
57 buf->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +010058 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +020059 buf->flags |= BF_FULL;
60
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020061 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020062}
63
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020064/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010065 * success, or the number of bytes available otherwise. If the chunk
Willy Tarreauf890dc92008-12-13 21:12:26 +010066 * has been written, its size is automatically reset to zero. The send limit is
67 * automatically adjusted with the amount of data written.
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010068 */
69int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
70{
71 int max;
72
73 if (chunk->len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020074 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010075
76 max = buffer_realign(buf);
77
78 if (chunk->len > max)
79 return max;
80
81 memcpy(buf->r, chunk->str, chunk->len);
82 buf->l += chunk->len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010083 buf->send_max += chunk->len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010084 buf->r += chunk->len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010085 buf->total += chunk->len;
Willy Tarreaua07a34e2009-08-16 23:27:46 +020086 if (buf->r == buf->data + buf->size)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010087 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020088
Willy Tarreaue393fe22008-08-16 22:18:07 +020089 buf->flags &= ~(BF_EMPTY|BF_FULL);
90 if (buf->l == 0)
91 buf->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +010092 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +020093 buf->flags |= BF_FULL;
94
95 chunk->len = 0;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020096 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010097}
98
Willy Tarreaubaaee002006-06-26 02:48:02 +020099/*
100 * this function writes the string <str> at position <pos> which must be in buffer <b>,
101 * and moves <end> just after the end of <str>.
102 * <b>'s parameters (l, r, w, h, lr) are recomputed to be valid after the shift.
103 * the shift value (positive or negative) is returned.
104 * If there's no space left, the move is not done.
105 *
106 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100107int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200108{
109 int delta;
110 int len;
111
112 len = strlen(str);
113 delta = len - (end - pos);
114
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200115 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116 return 0; /* no space left */
117
118 /* first, protect the end of the buffer */
119 memmove(end + delta, end, b->data + b->l - end);
120
121 /* now, copy str over pos */
122 memcpy(pos, str,len);
123
124 /* we only move data after the displaced zone */
125 if (b->r > pos) b->r += delta;
126 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200127 if (b->lr > pos) b->lr += delta;
128 b->l += delta;
129
Willy Tarreaue393fe22008-08-16 22:18:07 +0200130 b->flags &= ~(BF_EMPTY|BF_FULL);
131 if (b->l == 0)
132 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100133 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200134 b->flags |= BF_FULL;
135
Willy Tarreaubaaee002006-06-26 02:48:02 +0200136 return delta;
137}
138
139/*
140 * same except that the string length is given, which allows str to be NULL if
Willy Tarreauf890dc92008-12-13 21:12:26 +0100141 * len is 0. The send limit is *not* adjusted.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100143int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144{
145 int delta;
146
147 delta = len - (end - pos);
148
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200149 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150 return 0; /* no space left */
151
152 if (b->data + b->l < end) {
153 /* The data has been stolen, we could have crashed.
154 * Maybe we should abort() ? */
155 return 0;
156 }
157
158 /* first, protect the end of the buffer */
159 memmove(end + delta, end, b->data + b->l - end);
160
161 /* now, copy str over pos */
162 if (len)
163 memcpy(pos, str, len);
164
165 /* we only move data after the displaced zone */
166 if (b->r > pos) b->r += delta;
167 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168 if (b->lr > pos) b->lr += delta;
169 b->l += delta;
170
Willy Tarreaue393fe22008-08-16 22:18:07 +0200171 b->flags &= ~(BF_EMPTY|BF_FULL);
172 if (b->l == 0)
173 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100174 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200175 b->flags |= BF_FULL;
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 return delta;
178}
179
180
181/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100182 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
183 * argument informs about the length of string <str> so that we don't have to
184 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
185 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
Willy Tarreauf890dc92008-12-13 21:12:26 +0100186 * some circumstances. The send limit is *not* adjusted.
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100187 *
188 * The number of bytes added is returned on success. 0 is returned on failure.
189 */
190int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
191{
192 int delta;
193
194 delta = len + 2;
195
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200196 if (delta + b->r >= b->data + b->size)
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100197 return 0; /* no space left */
198
199 /* first, protect the end of the buffer */
200 memmove(pos + delta, pos, b->data + b->l - pos);
201
202 /* now, copy str over pos */
203 if (len && str) {
204 memcpy(pos, str, len);
205 pos[len] = '\r';
206 pos[len + 1] = '\n';
207 }
208
209 /* we only move data after the displaced zone */
210 if (b->r > pos) b->r += delta;
211 if (b->w > pos) b->w += delta;
212 if (b->lr > pos) b->lr += delta;
213 b->l += delta;
214
Willy Tarreaue393fe22008-08-16 22:18:07 +0200215 b->flags &= ~(BF_EMPTY|BF_FULL);
216 if (b->l == 0)
217 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100218 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200219 b->flags |= BF_FULL;
220
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100221 return delta;
222}
223
224
225/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100226 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
227 * at most <size> chars. If the size is over, nothing is added. Returns
228 * the new chunk size.
229 */
230int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
231{
232 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200233 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100234
235 va_start(argp, fmt);
Willy Tarreaudceaa082007-07-25 14:38:45 +0200236 ret = vsnprintf(chk->str + chk->len, size - chk->len, fmt, argp);
237 if (ret >= size - chk->len)
238 /* do not copy anything in case of truncation */
239 chk->str[chk->len] = 0;
240 else
241 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100242 va_end(argp);
243 return chk->len;
244}
245
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100246/*
247 * Dumps part or all of a buffer.
248 */
249void buffer_dump(FILE *o, struct buffer *b, int from, int to)
250{
251 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100252 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
253 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100254
255 if (!to || to > b->l)
256 to = b->l;
257
258 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
259 for (; from < to; from++) {
260 if ((from & 15) == 0)
261 fprintf(o, " %04x: ", from);
262 fprintf(o, "%02x ", b->data[from]);
263 if ((from & 15) == 7)
264 fprintf(o, "- ");
265 else if (((from & 15) == 15) && (from != to-1))
266 fprintf(o, "\n");
267 }
268 fprintf(o, "\n--\n");
269}
270
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100271
272/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273 * Local variables:
274 * c-indent-level: 8
275 * c-basic-offset: 8
276 * End:
277 */