blob: fa6b8a906ad7c5811efcd23b106d7d9fb76c2f6f [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
52 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020053}
54
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020055/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010056 * success, or the number of bytes available otherwise. If the chunk
57 * has been written, its size is automatically reset to zero.
58 */
59int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
60{
61 int max;
62
63 if (chunk->len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020064 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010065
66 max = buffer_realign(buf);
67
68 if (chunk->len > max)
69 return max;
70
71 memcpy(buf->r, chunk->str, chunk->len);
72 buf->l += chunk->len;
73 buf->r += chunk->len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010074 buf->total += chunk->len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010075 if (buf->r == buf->data + BUFSIZE)
76 buf->r = buf->data;
77 chunk->len = 0;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020078
79 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010080}
81
Willy Tarreaubaaee002006-06-26 02:48:02 +020082/*
83 * this function writes the string <str> at position <pos> which must be in buffer <b>,
84 * and moves <end> just after the end of <str>.
85 * <b>'s parameters (l, r, w, h, lr) are recomputed to be valid after the shift.
86 * the shift value (positive or negative) is returned.
87 * If there's no space left, the move is not done.
88 *
89 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +010090int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +020091{
92 int delta;
93 int len;
94
95 len = strlen(str);
96 delta = len - (end - pos);
97
98 if (delta + b->r >= b->data + BUFSIZE)
99 return 0; /* no space left */
100
101 /* first, protect the end of the buffer */
102 memmove(end + delta, end, b->data + b->l - end);
103
104 /* now, copy str over pos */
105 memcpy(pos, str,len);
106
107 /* we only move data after the displaced zone */
108 if (b->r > pos) b->r += delta;
109 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200110 if (b->lr > pos) b->lr += delta;
111 b->l += delta;
112
113 return delta;
114}
115
116/*
117 * same except that the string length is given, which allows str to be NULL if
118 * len is 0.
119 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100120int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200121{
122 int delta;
123
124 delta = len - (end - pos);
125
126 if (delta + b->r >= b->data + BUFSIZE)
127 return 0; /* no space left */
128
129 if (b->data + b->l < end) {
130 /* The data has been stolen, we could have crashed.
131 * Maybe we should abort() ? */
132 return 0;
133 }
134
135 /* first, protect the end of the buffer */
136 memmove(end + delta, end, b->data + b->l - end);
137
138 /* now, copy str over pos */
139 if (len)
140 memcpy(pos, str, len);
141
142 /* we only move data after the displaced zone */
143 if (b->r > pos) b->r += delta;
144 if (b->w > pos) b->w += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200145 if (b->lr > pos) b->lr += delta;
146 b->l += delta;
147
148 return delta;
149}
150
151
152/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100153 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
154 * argument informs about the length of string <str> so that we don't have to
155 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
156 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
157 * some circumstances.
158 *
159 * The number of bytes added is returned on success. 0 is returned on failure.
160 */
161int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
162{
163 int delta;
164
165 delta = len + 2;
166
167 if (delta + b->r >= b->data + BUFSIZE)
168 return 0; /* no space left */
169
170 /* first, protect the end of the buffer */
171 memmove(pos + delta, pos, b->data + b->l - pos);
172
173 /* now, copy str over pos */
174 if (len && str) {
175 memcpy(pos, str, len);
176 pos[len] = '\r';
177 pos[len + 1] = '\n';
178 }
179
180 /* we only move data after the displaced zone */
181 if (b->r > pos) b->r += delta;
182 if (b->w > pos) b->w += delta;
183 if (b->lr > pos) b->lr += delta;
184 b->l += delta;
185
186 return delta;
187}
188
189
190/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100191 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
192 * at most <size> chars. If the size is over, nothing is added. Returns
193 * the new chunk size.
194 */
195int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
196{
197 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200198 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100199
200 va_start(argp, fmt);
Willy Tarreaudceaa082007-07-25 14:38:45 +0200201 ret = vsnprintf(chk->str + chk->len, size - chk->len, fmt, argp);
202 if (ret >= size - chk->len)
203 /* do not copy anything in case of truncation */
204 chk->str[chk->len] = 0;
205 else
206 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100207 va_end(argp);
208 return chk->len;
209}
210
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100211/*
212 * Dumps part or all of a buffer.
213 */
214void buffer_dump(FILE *o, struct buffer *b, int from, int to)
215{
216 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100217 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
218 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100219
220 if (!to || to > b->l)
221 to = b->l;
222
223 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
224 for (; from < to; from++) {
225 if ((from & 15) == 0)
226 fprintf(o, " %04x: ", from);
227 fprintf(o, "%02x ", b->data[from]);
228 if ((from & 15) == 7)
229 fprintf(o, "- ");
230 else if (((from & 15) == 15) && (from != to-1))
231 fprintf(o, "\n");
232 }
233 fprintf(o, "\n--\n");
234}
235
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100236
237/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 * Local variables:
239 * c-indent-level: 8
240 * c-basic-offset: 8
241 * End:
242 */