blob: c8681cfb8c6487153fec8cfa96bca8c603bb025f [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>
20
Willy Tarreau7341d942007-05-13 19:56:02 +020021struct pool_head *pool2_buffer;
22
23
24/* perform minimal intializations, report 0 in case of error, 1 if OK. */
25int init_buffer()
26{
27 pool2_buffer = create_pool("buffer", sizeof(struct buffer), MEM_F_SHARED);
28 return pool2_buffer != NULL;
29}
30
Willy Tarreaubaaee002006-06-26 02:48:02 +020031
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020032/* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
Willy Tarreauf890dc92008-12-13 21:12:26 +010033 * success, or the number of bytes available otherwise. The send limit is
34 * automatically adjusted with the amount of data written.
Willy Tarreaubaaee002006-06-26 02:48:02 +020035 * FIXME-20060521: handle unaligned data.
36 */
37int buffer_write(struct buffer *buf, const char *msg, int len)
38{
39 int max;
40
41 max = buffer_realign(buf);
42
43 if (len > max)
44 return max;
45
46 memcpy(buf->r, msg, len);
47 buf->l += len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010048 buf->send_max += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020049 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010050 buf->total += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020051 if (buf->r == buf->data + BUFSIZE)
52 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020053
Willy Tarreaue393fe22008-08-16 22:18:07 +020054 buf->flags &= ~(BF_EMPTY|BF_FULL);
55 if (buf->l == 0)
56 buf->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +010057 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +020058 buf->flags |= BF_FULL;
59
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020060 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020061}
62
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020063/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010064 * success, or the number of bytes available otherwise. If the chunk
Willy Tarreauf890dc92008-12-13 21:12:26 +010065 * has been written, its size is automatically reset to zero. The send limit is
66 * automatically adjusted with the amount of data written.
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010067 */
68int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
69{
70 int max;
71
72 if (chunk->len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020073 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010074
75 max = buffer_realign(buf);
76
77 if (chunk->len > max)
78 return max;
79
80 memcpy(buf->r, chunk->str, chunk->len);
81 buf->l += chunk->len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010082 buf->send_max += chunk->len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010083 buf->r += chunk->len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010084 buf->total += chunk->len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010085 if (buf->r == buf->data + BUFSIZE)
86 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020087
Willy Tarreaue393fe22008-08-16 22:18:07 +020088 buf->flags &= ~(BF_EMPTY|BF_FULL);
89 if (buf->l == 0)
90 buf->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +010091 if (buf->l >= buf->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +020092 buf->flags |= BF_FULL;
93
94 chunk->len = 0;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020095 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010096}
97
Willy Tarreaubaaee002006-06-26 02:48:02 +020098/*
99 * this function writes the string <str> at position <pos> which must be in buffer <b>,
100 * and moves <end> just after the end of <str>.
101 * <b>'s parameters (l, r, w, h, lr) are recomputed to be valid after the shift.
102 * the shift value (positive or negative) is returned.
103 * If there's no space left, the move is not done.
104 *
105 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100106int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200107{
108 int delta;
109 int len;
110
111 len = strlen(str);
112 delta = len - (end - pos);
113
114 if (delta + b->r >= b->data + BUFSIZE)
115 return 0; /* no space left */
116
117 /* first, protect the end of the buffer */
118 memmove(end + delta, end, b->data + b->l - end);
119
120 /* now, copy str over pos */
121 memcpy(pos, str,len);
122
123 /* we only move data after the displaced zone */
124 if (b->r > pos) b->r += delta;
125 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126 if (b->lr > pos) b->lr += delta;
127 b->l += delta;
128
Willy Tarreaue393fe22008-08-16 22:18:07 +0200129 b->flags &= ~(BF_EMPTY|BF_FULL);
130 if (b->l == 0)
131 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100132 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200133 b->flags |= BF_FULL;
134
Willy Tarreaubaaee002006-06-26 02:48:02 +0200135 return delta;
136}
137
138/*
139 * same except that the string length is given, which allows str to be NULL if
Willy Tarreauf890dc92008-12-13 21:12:26 +0100140 * len is 0. The send limit is *not* adjusted.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100142int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143{
144 int delta;
145
146 delta = len - (end - pos);
147
148 if (delta + b->r >= b->data + BUFSIZE)
149 return 0; /* no space left */
150
151 if (b->data + b->l < end) {
152 /* The data has been stolen, we could have crashed.
153 * Maybe we should abort() ? */
154 return 0;
155 }
156
157 /* first, protect the end of the buffer */
158 memmove(end + delta, end, b->data + b->l - end);
159
160 /* now, copy str over pos */
161 if (len)
162 memcpy(pos, str, len);
163
164 /* we only move data after the displaced zone */
165 if (b->r > pos) b->r += delta;
166 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167 if (b->lr > pos) b->lr += delta;
168 b->l += delta;
169
Willy Tarreaue393fe22008-08-16 22:18:07 +0200170 b->flags &= ~(BF_EMPTY|BF_FULL);
171 if (b->l == 0)
172 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100173 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200174 b->flags |= BF_FULL;
175
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 return delta;
177}
178
179
180/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100181 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
182 * argument informs about the length of string <str> so that we don't have to
183 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
184 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
Willy Tarreauf890dc92008-12-13 21:12:26 +0100185 * some circumstances. The send limit is *not* adjusted.
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100186 *
187 * The number of bytes added is returned on success. 0 is returned on failure.
188 */
189int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
190{
191 int delta;
192
193 delta = len + 2;
194
195 if (delta + b->r >= b->data + BUFSIZE)
196 return 0; /* no space left */
197
198 /* first, protect the end of the buffer */
199 memmove(pos + delta, pos, b->data + b->l - pos);
200
201 /* now, copy str over pos */
202 if (len && str) {
203 memcpy(pos, str, len);
204 pos[len] = '\r';
205 pos[len + 1] = '\n';
206 }
207
208 /* we only move data after the displaced zone */
209 if (b->r > pos) b->r += delta;
210 if (b->w > pos) b->w += delta;
211 if (b->lr > pos) b->lr += delta;
212 b->l += delta;
213
Willy Tarreaue393fe22008-08-16 22:18:07 +0200214 b->flags &= ~(BF_EMPTY|BF_FULL);
215 if (b->l == 0)
216 b->flags |= BF_EMPTY;
Willy Tarreau03d60bb2009-01-09 11:13:00 +0100217 if (b->l >= b->max_len)
Willy Tarreaue393fe22008-08-16 22:18:07 +0200218 b->flags |= BF_FULL;
219
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100220 return delta;
221}
222
223
224/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100225 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
226 * at most <size> chars. If the size is over, nothing is added. Returns
227 * the new chunk size.
228 */
229int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
230{
231 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200232 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100233
234 va_start(argp, fmt);
Willy Tarreaudceaa082007-07-25 14:38:45 +0200235 ret = vsnprintf(chk->str + chk->len, size - chk->len, fmt, argp);
236 if (ret >= size - chk->len)
237 /* do not copy anything in case of truncation */
238 chk->str[chk->len] = 0;
239 else
240 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100241 va_end(argp);
242 return chk->len;
243}
244
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100245/*
246 * Dumps part or all of a buffer.
247 */
248void buffer_dump(FILE *o, struct buffer *b, int from, int to)
249{
250 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100251 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
252 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100253
254 if (!to || to > b->l)
255 to = b->l;
256
257 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
258 for (; from < to; from++) {
259 if ((from & 15) == 0)
260 fprintf(o, " %04x: ", from);
261 fprintf(o, "%02x ", b->data[from]);
262 if ((from & 15) == 7)
263 fprintf(o, "- ");
264 else if (((from & 15) == 15) && (from != to-1))
265 fprintf(o, "\n");
266 }
267 fprintf(o, "\n--\n");
268}
269
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100270
271/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 * Local variables:
273 * c-indent-level: 8
274 * c-basic-offset: 8
275 * End:
276 */