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