blob: f7e672d0708568a5ef3c86f94f1e586330cff35a [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 Tarreaubaaee002006-06-26 02:48:02 +020033 * success, or the number of bytes available otherwise.
34 * FIXME-20060521: handle unaligned data.
35 */
36int buffer_write(struct buffer *buf, const char *msg, int len)
37{
38 int max;
39
40 max = buffer_realign(buf);
41
42 if (len > max)
43 return max;
44
45 memcpy(buf->r, msg, len);
46 buf->l += len;
47 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010048 buf->total += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020049 if (buf->r == buf->data + BUFSIZE)
50 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020051
Willy Tarreaue393fe22008-08-16 22:18:07 +020052 buf->flags &= ~(BF_EMPTY|BF_FULL);
53 if (buf->l == 0)
54 buf->flags |= BF_EMPTY;
55 if (buf->l >= buf->rlim - buf->data)
56 buf->flags |= BF_FULL;
57
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020058 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020059}
60
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020061/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010062 * success, or the number of bytes available otherwise. If the chunk
63 * has been written, its size is automatically reset to zero.
64 */
65int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
66{
67 int max;
68
69 if (chunk->len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020070 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010071
72 max = buffer_realign(buf);
73
74 if (chunk->len > max)
75 return max;
76
77 memcpy(buf->r, chunk->str, chunk->len);
78 buf->l += chunk->len;
79 buf->r += chunk->len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010080 buf->total += chunk->len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010081 if (buf->r == buf->data + BUFSIZE)
82 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020083
Willy Tarreaue393fe22008-08-16 22:18:07 +020084 buf->flags &= ~(BF_EMPTY|BF_FULL);
85 if (buf->l == 0)
86 buf->flags |= BF_EMPTY;
87 if (buf->l >= buf->rlim - buf->data)
88 buf->flags |= BF_FULL;
89
90 chunk->len = 0;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020091 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010092}
93
Willy Tarreaubaaee002006-06-26 02:48:02 +020094/*
95 * this function writes the string <str> at position <pos> which must be in buffer <b>,
96 * and moves <end> just after the end of <str>.
97 * <b>'s parameters (l, r, w, h, lr) are recomputed to be valid after the shift.
98 * the shift value (positive or negative) is returned.
99 * If there's no space left, the move is not done.
100 *
101 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100102int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200103{
104 int delta;
105 int len;
106
107 len = strlen(str);
108 delta = len - (end - pos);
109
110 if (delta + b->r >= b->data + BUFSIZE)
111 return 0; /* no space left */
112
113 /* first, protect the end of the buffer */
114 memmove(end + delta, end, b->data + b->l - end);
115
116 /* now, copy str over pos */
117 memcpy(pos, str,len);
118
119 /* we only move data after the displaced zone */
120 if (b->r > pos) b->r += delta;
121 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200122 if (b->lr > pos) b->lr += delta;
123 b->l += delta;
124
Willy Tarreaue393fe22008-08-16 22:18:07 +0200125 b->flags &= ~(BF_EMPTY|BF_FULL);
126 if (b->l == 0)
127 b->flags |= BF_EMPTY;
128 if (b->l >= b->rlim - b->data)
129 b->flags |= BF_FULL;
130
Willy Tarreaubaaee002006-06-26 02:48:02 +0200131 return delta;
132}
133
134/*
135 * same except that the string length is given, which allows str to be NULL if
136 * len is 0.
137 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100138int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139{
140 int delta;
141
142 delta = len - (end - pos);
143
144 if (delta + b->r >= b->data + BUFSIZE)
145 return 0; /* no space left */
146
147 if (b->data + b->l < end) {
148 /* The data has been stolen, we could have crashed.
149 * Maybe we should abort() ? */
150 return 0;
151 }
152
153 /* first, protect the end of the buffer */
154 memmove(end + delta, end, b->data + b->l - end);
155
156 /* now, copy str over pos */
157 if (len)
158 memcpy(pos, str, len);
159
160 /* we only move data after the displaced zone */
161 if (b->r > pos) b->r += delta;
162 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 if (b->lr > pos) b->lr += delta;
164 b->l += delta;
165
Willy Tarreaue393fe22008-08-16 22:18:07 +0200166 b->flags &= ~(BF_EMPTY|BF_FULL);
167 if (b->l == 0)
168 b->flags |= BF_EMPTY;
169 if (b->l >= b->rlim - b->data)
170 b->flags |= BF_FULL;
171
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172 return delta;
173}
174
175
176/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100177 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
178 * argument informs about the length of string <str> so that we don't have to
179 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
180 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
181 * some circumstances.
182 *
183 * The number of bytes added is returned on success. 0 is returned on failure.
184 */
185int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
186{
187 int delta;
188
189 delta = len + 2;
190
191 if (delta + b->r >= b->data + BUFSIZE)
192 return 0; /* no space left */
193
194 /* first, protect the end of the buffer */
195 memmove(pos + delta, pos, b->data + b->l - pos);
196
197 /* now, copy str over pos */
198 if (len && str) {
199 memcpy(pos, str, len);
200 pos[len] = '\r';
201 pos[len + 1] = '\n';
202 }
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;
207 if (b->lr > pos) b->lr += delta;
208 b->l += delta;
209
Willy Tarreaue393fe22008-08-16 22:18:07 +0200210 b->flags &= ~(BF_EMPTY|BF_FULL);
211 if (b->l == 0)
212 b->flags |= BF_EMPTY;
213 if (b->l >= b->rlim - b->data)
214 b->flags |= BF_FULL;
215
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100216 return delta;
217}
218
219
220/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100221 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
222 * at most <size> chars. If the size is over, nothing is added. Returns
223 * the new chunk size.
224 */
225int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
226{
227 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200228 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100229
230 va_start(argp, fmt);
Willy Tarreaudceaa082007-07-25 14:38:45 +0200231 ret = vsnprintf(chk->str + chk->len, size - chk->len, fmt, argp);
232 if (ret >= size - chk->len)
233 /* do not copy anything in case of truncation */
234 chk->str[chk->len] = 0;
235 else
236 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100237 va_end(argp);
238 return chk->len;
239}
240
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100241/*
242 * Dumps part or all of a buffer.
243 */
244void buffer_dump(FILE *o, struct buffer *b, int from, int to)
245{
246 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100247 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
248 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100249
250 if (!to || to > b->l)
251 to = b->l;
252
253 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
254 for (; from < to; from++) {
255 if ((from & 15) == 0)
256 fprintf(o, " %04x: ", from);
257 fprintf(o, "%02x ", b->data[from]);
258 if ((from & 15) == 7)
259 fprintf(o, "- ");
260 else if (((from & 15) == 15) && (from != to-1))
261 fprintf(o, "\n");
262 }
263 fprintf(o, "\n--\n");
264}
265
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100266
267/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 * Local variables:
269 * c-indent-level: 8
270 * c-basic-offset: 8
271 * End:
272 */