Coverage Report

Created: 2025-06-20 06:16

/src/haproxy/src/channel.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Channel management functions.
3
 *
4
 * Copyright 2000-2014 Willy Tarreau <w@1wt.eu>
5
 *
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
13
#include <ctype.h>
14
#include <stdarg.h>
15
#include <stdio.h>
16
#include <string.h>
17
18
#include <haproxy/api.h>
19
#include <haproxy/buf.h>
20
#include <haproxy/channel.h>
21
22
23
/* Schedule up to <bytes> more bytes to be forwarded via the channel without
24
 * notifying the owner task. Any data pending in the buffer are scheduled to be
25
 * sent as well, within the limit of the number of bytes to forward. This must
26
 * be the only method to use to schedule bytes to be forwarded. If the requested
27
 * number is too large, it is automatically adjusted. The number of bytes taken
28
 * into account is returned. Directly touching ->to_forward will cause lockups
29
 * when buf->o goes down to zero if nobody is ready to push the remaining data.
30
 */
31
unsigned long long __channel_forward(struct channel *chn, unsigned long long bytes)
32
0
{
33
0
  unsigned int budget;
34
0
  unsigned int forwarded;
35
36
  /* This is more of a safety measure as it's not supposed to happen in
37
   * regular code paths.
38
   */
39
0
  if (unlikely(chn->to_forward == CHN_INFINITE_FORWARD)) {
40
0
    c_adv(chn, ci_data(chn));
41
0
    return bytes;
42
0
  }
43
44
  /* Bound the transferred size to a 32-bit count since all our values
45
   * are 32-bit, and we don't want to reach CHN_INFINITE_FORWARD.
46
   */
47
0
  budget = MIN(bytes, CHN_INFINITE_FORWARD - 1);
48
49
  /* transfer as much as we can of buf->i */
50
0
  forwarded = MIN(ci_data(chn), budget);
51
0
  c_adv(chn, forwarded);
52
0
  budget -= forwarded;
53
54
0
  if (!budget)
55
0
    return forwarded;
56
57
  /* Now we must ensure chn->to_forward sats below CHN_INFINITE_FORWARD,
58
   * which also implies it won't overflow. It's less operations in 64-bit.
59
   */
60
0
  bytes = (unsigned long long)chn->to_forward + budget;
61
0
  if (bytes >= CHN_INFINITE_FORWARD)
62
0
    bytes = CHN_INFINITE_FORWARD - 1;
63
0
  budget = bytes - chn->to_forward;
64
65
0
  chn->to_forward += budget;
66
0
  forwarded += budget;
67
0
  return forwarded;
68
0
}
69
70
/* writes <len> bytes from message <msg> to the channel's buffer. Returns -1 in
71
 * case of success, -2 if the message is larger than the buffer size, or the
72
 * number of bytes available otherwise. The send limit is automatically
73
 * adjusted to the amount of data written. FIXME-20060521: handle unaligned
74
 * data. Note: this function appends data to the buffer's output and possibly
75
 * overwrites any pending input data which are assumed not to exist.
76
 */
77
int co_inject(struct channel *chn, const char *msg, int len)
78
0
{
79
0
  int max;
80
81
0
  if (len == 0)
82
0
    return -1;
83
84
0
  if (len < 0 || len > c_size(chn)) {
85
    /* we can't write this chunk and will never be able to, because
86
     * it is larger than the buffer. This must be reported as an
87
     * error. Then we return -2 so that writers that don't care can
88
     * ignore it and go on, and others can check for this value.
89
     */
90
0
    return -2;
91
0
  }
92
93
0
  c_realign_if_empty(chn);
94
0
  max = b_contig_space(&chn->buf);
95
0
  if (len > max)
96
0
    return max;
97
98
0
  memcpy(co_tail(chn), msg, len);
99
0
  b_add(&chn->buf, len);
100
0
  c_adv(chn, len);
101
0
  chn->total += len;
102
0
  return -1;
103
0
}
104
105
/* Tries to copy character <c> into the channel's buffer after some length
106
 * controls. The chn->o and to_forward pointers are updated. If the channel
107
 * input is closed, -2 is returned. If there is not enough room left in the
108
 * buffer, -1 is returned. Otherwise the number of bytes copied is returned
109
 * (1). Channel flag READ_PARTIAL is updated if some data can be transferred.
110
 */
111
int ci_putchr(struct channel *chn, char c)
112
0
{
113
0
  if (unlikely(channel_input_closed(chn)))
114
0
    return -2;
115
116
0
  if (!channel_may_recv(chn))
117
0
    return -1;
118
119
0
  *ci_tail(chn) = c;
120
121
0
  b_add(&chn->buf, 1);
122
0
  chn->flags |= CF_READ_EVENT;
123
124
0
  if (chn->to_forward >= 1) {
125
0
    if (chn->to_forward != CHN_INFINITE_FORWARD)
126
0
      chn->to_forward--;
127
0
    c_adv(chn, 1);
128
0
  }
129
130
0
  chn->total++;
131
0
  return 1;
132
0
}
133
134
/* Tries to copy block <blk> at once into the channel's buffer after length
135
 * controls. The chn->o and to_forward pointers are updated. If the channel
136
 * input is closed, -2 is returned. If the block is too large for this buffer,
137
 * -3 is returned. If there is not enough room left in the buffer, -1 is
138
 * returned. Otherwise the number of bytes copied is returned (0 being a valid
139
 * number). Channel flag READ_PARTIAL is updated if some data can be
140
 * transferred.
141
 */
142
int ci_putblk(struct channel *chn, const char *blk, int len)
143
0
{
144
0
  int max;
145
146
0
  if (unlikely(channel_input_closed(chn)))
147
0
    return -2;
148
149
0
  if (len < 0)
150
0
    return -3;
151
152
0
  max = channel_recv_limit(chn);
153
0
  if (unlikely(len > max - c_data(chn))) {
154
    /* we can't write this chunk right now because the buffer is
155
     * almost full or because the block is too large. Returns
156
     * -3 if block is too large for this buffer. Or -1 if the
157
     * room left is not large enough.
158
     */
159
0
    if (len > max)
160
0
      return -3;
161
162
0
    return -1;
163
0
  }
164
165
0
  if (unlikely(len == 0))
166
0
    return 0;
167
168
  /* OK so the data fits in the buffer in one or two blocks */
169
0
  max = b_contig_space(&chn->buf);
170
0
  memcpy(ci_tail(chn), blk, MIN(len, max));
171
0
  if (len > max)
172
0
    memcpy(c_orig(chn), blk + max, len - max);
173
174
0
  b_add(&chn->buf, len);
175
0
  channel_add_input(chn, len);
176
0
  return len;
177
0
}
178
179
/* Locates the longest part of the channel's output buffer that is composed
180
 * exclusively of characters not in the <delim> set, and delimited by one of
181
 * these characters, and returns the initial part and the first of such
182
 * delimiters. A single escape character in <escape> may be specified so that
183
 * when not 0 and found, the character that follows it is never taken as a
184
 * delimiter. Note that <delim> cannot contain the zero byte, hence this
185
 * function is not usable with byte zero as a delimiter.
186
 *
187
 * Return values :
188
 *   >0 : number of bytes read. Includes the sep if present before len or end.
189
 *   =0 : no sep before end found. <str> is left undefined.
190
 *   <0 : no more bytes readable because output is shut.
191
 * The channel status is not changed. The caller must call co_skip() to
192
 * update it. One of the delimiters is waited for as long as neither the buffer
193
 * nor the output are full. If either of them is full, the string may be
194
 * returned as is, without the delimiter.
195
 */
196
int co_getdelim(const struct channel *chn, char *str, int len, const char *delim, char escape)
197
0
{
198
0
  uchar delim_map[256 / 8];
199
0
  int found, escaped;
200
0
  uint pos, bit;
201
0
  int ret, max;
202
0
  uchar b;
203
0
  char *p;
204
205
0
  ret = 0;
206
0
  max = len;
207
208
  /* closed or empty + imminent close = -1; empty = 0 */
209
0
  if (unlikely((chn_cons(chn)->flags & SC_FL_SHUT_DONE) || !co_data(chn))) {
210
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
211
0
      ret = -1;
212
0
    goto out;
213
0
  }
214
215
0
  p = co_head(chn);
216
217
0
  if (max > co_data(chn)) {
218
0
    max = co_data(chn);
219
0
    str[max-1] = 0;
220
0
  }
221
222
  /* create the byte map */
223
0
  memset(delim_map, 0, sizeof(delim_map));
224
0
  while ((b = *delim)) {
225
0
    pos = b >> 3;
226
0
    bit = b &  7;
227
0
    delim_map[pos] |= 1 << bit;
228
0
    delim++;
229
0
  }
230
231
0
  found = escaped = 0;
232
0
  while (max) {
233
0
    *str++ = b = *p;
234
0
    ret++;
235
0
    max--;
236
237
0
    if (escape && (escaped || *p == escape)) {
238
0
      escaped = !escaped;
239
0
      goto skip;
240
0
    }
241
242
0
    pos = b >> 3;
243
0
    bit = b &  7;
244
0
    if (delim_map[pos] & (1 << bit)) {
245
0
      found = 1;
246
0
      break;
247
0
    }
248
0
  skip:
249
0
    p = b_next(&chn->buf, p);
250
0
  }
251
252
0
  if (ret > 0 && ret < len &&
253
0
      (ret < co_data(chn) || channel_may_recv(chn)) &&
254
0
      !found &&
255
0
      !(chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)))
256
0
    ret = 0;
257
0
 out:
258
0
  if (max)
259
0
    *str = 0;
260
0
  return ret;
261
0
}
262
263
/* Gets one text word out of a channel's buffer from a stream connector.
264
 * Return values :
265
 *   >0 : number of bytes read. Includes the sep if present before len or end.
266
 *   =0 : no sep before end found. <str> is left undefined.
267
 *   <0 : no more bytes readable because output is shut.
268
 * The channel status is not changed. The caller must call co_skip() to
269
 * update it. The line separator is waited for as long as neither the buffer
270
 * nor the output are full. If either of them is full, the string may be
271
 * returned as is, without the line separator.
272
 */
273
int co_getword(const struct channel *chn, char *str, int len, char sep)
274
0
{
275
0
  int ret, max;
276
0
  char *p;
277
278
0
  ret = 0;
279
0
  max = len;
280
281
  /* closed or empty + imminent close = -1; empty = 0 */
282
0
  if (unlikely((chn_cons(chn)->flags & SC_FL_SHUT_DONE) || !co_data(chn))) {
283
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
284
0
      ret = -1;
285
0
    goto out;
286
0
  }
287
288
0
  p = co_head(chn);
289
290
0
  if (max > co_data(chn)) {
291
0
    max = co_data(chn);
292
0
    str[max-1] = 0;
293
0
  }
294
0
  while (max) {
295
0
    *str++ = *p;
296
0
    ret++;
297
0
    max--;
298
299
0
    if (*p == sep)
300
0
      break;
301
0
    p = b_next(&chn->buf, p);
302
0
  }
303
0
  if (ret > 0 && ret < len &&
304
0
      (ret < co_data(chn) || channel_may_recv(chn)) &&
305
0
      *(str-1) != sep &&
306
0
      !(chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)))
307
0
    ret = 0;
308
0
 out:
309
0
  if (max)
310
0
    *str = 0;
311
0
  return ret;
312
0
}
313
314
/* Gets one text line out of a channel's buffer from a stream connector.
315
 * Return values :
316
 *   >0 : number of bytes read. Includes the \n if present before len or end.
317
 *   =0 : no '\n' before end found. <str> is left undefined.
318
 *   <0 : no more bytes readable because output is shut.
319
 * The channel status is not changed. The caller must call co_skip() to
320
 * update it. The '\n' is waited for as long as neither the buffer nor the
321
 * output are full. If either of them is full, the string may be returned
322
 * as is, without the '\n'.
323
 */
324
int co_getline(const struct channel *chn, char *str, int len)
325
0
{
326
0
  int ret, max;
327
0
  size_t ofs;
328
329
0
  ret = 0;
330
0
  max = len;
331
332
  /* closed or empty + imminent close = -1; empty = 0 */
333
0
  if (unlikely((chn_cons(chn)->flags & SC_FL_SHUT_DONE) || !co_data(chn))) {
334
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
335
0
      ret = -1;
336
0
    goto out;
337
0
  }
338
339
0
  if (max > co_data(chn)) {
340
0
    max = co_data(chn);
341
0
    str[max-1] = 0;
342
0
  }
343
344
0
  ofs = 0;
345
346
0
  while (max) {
347
0
    size_t contig = b_contig_data(&chn->buf, ofs);
348
0
    size_t len = MIN(max, contig);
349
0
    const char *beg = b_peek(&chn->buf, ofs);
350
0
    const char *lf = memchr(beg, '\n', len);
351
352
0
    if (lf) /* take the LF with it before stopping */
353
0
      len = lf + 1 - beg;
354
355
0
    memcpy(str, beg, len);
356
0
    ret += len;
357
0
    str += len;
358
0
    ofs += len;
359
0
    max -= len;
360
361
0
    if (lf)
362
0
      break;
363
0
  }
364
0
  if (ret > 0 && ret < len &&
365
0
      (ret < co_data(chn) || channel_may_recv(chn)) &&
366
0
      *(str-1) != '\n' &&
367
0
      !(chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)))
368
0
    ret = 0;
369
0
 out:
370
0
  if (max)
371
0
    *str = 0;
372
0
  return ret;
373
0
}
374
375
/* Gets one char of data from a channel's buffer,
376
 * Return values :
377
 *    1 : number of bytes read, equal to requested size.
378
 *   =0 : not enough data available. <c> is left undefined.
379
 *   <0 : no more bytes readable because output is shut.
380
 * The channel status is not changed. The caller must call co_skip() to
381
 * update it.
382
 */
383
int co_getchar(const struct channel *chn, char *c)
384
0
{
385
0
  if (chn_cons(chn)->flags & SC_FL_SHUT_DONE)
386
0
    return -1;
387
388
0
  if (unlikely(co_data(chn) == 0)) {
389
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
390
0
      return -1;
391
0
    return 0;
392
0
  }
393
394
0
  *c = *(co_head(chn));
395
0
  return 1;
396
0
}
397
398
/* Gets one full block of data at once from a channel's buffer, optionally from
399
 * a specific offset. Return values :
400
 *   >0 : number of bytes read, equal to requested size.
401
 *   =0 : not enough data available. <blk> is left undefined.
402
 *   <0 : no more bytes readable because output is shut.
403
 * The channel status is not changed. The caller must call co_skip() to
404
 * update it.
405
 */
406
int co_getblk(const struct channel *chn, char *blk, int len, int offset)
407
0
{
408
0
  if (chn_cons(chn)->flags & SC_FL_SHUT_DONE)
409
0
    return -1;
410
411
0
  if (len + offset > co_data(chn) || co_data(chn) == 0) {
412
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
413
0
      return -1;
414
0
    return 0;
415
0
  }
416
417
0
  return b_getblk(&chn->buf, blk, len, offset);
418
0
}
419
420
/* Gets one or two blocks of data at once from a channel's output buffer.
421
 * Return values :
422
 *   >0 : number of blocks filled (1 or 2). blk1 is always filled before blk2.
423
 *   =0 : not enough data available. <blk*> are left undefined.
424
 *   <0 : no more bytes readable because output is shut.
425
 * The channel status is not changed. The caller must call co_skip() to
426
 * update it. Unused buffers are left in an undefined state.
427
 */
428
int co_getblk_nc(const struct channel *chn, const char **blk1, size_t *len1, const char **blk2, size_t *len2)
429
0
{
430
0
  if (unlikely(co_data(chn) == 0)) {
431
0
    if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
432
0
      return -1;
433
0
    return 0;
434
0
  }
435
436
0
  return b_getblk_nc(&chn->buf, blk1, len1, blk2, len2, 0, co_data(chn));
437
0
}
438
439
/* Gets one text line out of a channel's output buffer from a stream connector.
440
 * Return values :
441
 *   >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
442
 *   =0 : not enough data available.
443
 *   <0 : no more bytes readable because output is shut.
444
 * The '\n' is waited for as long as neither the buffer nor the output are
445
 * full. If either of them is full, the string may be returned as is, without
446
 * the '\n'. Unused buffers are left in an undefined state.
447
 */
448
int co_getline_nc(const struct channel *chn,
449
                  const char **blk1, size_t *len1,
450
                  const char **blk2, size_t *len2)
451
0
{
452
0
  int retcode;
453
0
  int l;
454
455
0
  retcode = co_getblk_nc(chn, blk1, len1, blk2, len2);
456
0
  if (unlikely(retcode <= 0))
457
0
    return retcode;
458
459
0
  for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);
460
0
  if (l < *len1 && (*blk1)[l] == '\n') {
461
0
    *len1 = l + 1;
462
0
    return 1;
463
0
  }
464
465
0
  if (retcode >= 2) {
466
0
    for (l = 0; l < *len2 && (*blk2)[l] != '\n'; l++);
467
0
    if (l < *len2 && (*blk2)[l] == '\n') {
468
0
      *len2 = l + 1;
469
0
      return 2;
470
0
    }
471
0
  }
472
473
0
  if (chn_cons(chn)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) {
474
    /* If we have found no LF and the buffer is shut, then
475
     * the resulting string is made of the concatenation of
476
     * the pending blocks (1 or 2).
477
     */
478
0
    return retcode;
479
0
  }
480
481
  /* No LF yet and not shut yet */
482
0
  return 0;
483
0
}
484
485
/* Gets one full block of data at once from a channel's input buffer.
486
 * This function can return the data slitted in one or two blocks.
487
 * Return values :
488
 *   >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
489
 *   =0 : not enough data available.
490
 *   <0 : no more bytes readable because input is shut.
491
 */
492
int ci_getblk_nc(const struct channel *chn,
493
                 char **blk1, size_t *len1,
494
                 char **blk2, size_t *len2)
495
0
{
496
0
  if (unlikely(ci_data(chn) == 0)) {
497
0
    if (chn_prod(chn)->flags & (SC_FL_EOS|SC_FL_ABRT_DONE))
498
0
      return -1;
499
0
    return 0;
500
0
  }
501
502
0
  if (unlikely(ci_head(chn) + ci_data(chn) > c_wrap(chn))) {
503
0
    *blk1 = ci_head(chn);
504
0
    *len1 = c_wrap(chn) - ci_head(chn);
505
0
    *blk2 = c_orig(chn);
506
0
    *len2 = ci_data(chn) - *len1;
507
0
    return 2;
508
0
  }
509
510
0
  *blk1 = ci_head(chn);
511
0
  *len1 = ci_data(chn);
512
0
  return 1;
513
0
}
514
515
/* Gets one text line out of a channel's input buffer from a stream connector.
516
 * Return values :
517
 *   >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
518
 *   =0 : not enough data available.
519
 *   <0 : no more bytes readable because output is shut.
520
 * The '\n' is waited for as long as neither the buffer nor the input are
521
 * full. If either of them is full, the string may be returned as is, without
522
 * the '\n'. Unused buffers are left in an undefined state.
523
 */
524
int ci_getline_nc(const struct channel *chn,
525
                  char **blk1, size_t *len1,
526
                  char **blk2, size_t *len2)
527
0
{
528
0
  int retcode;
529
0
  int l;
530
531
0
  retcode = ci_getblk_nc(chn, blk1, len1, blk2, len2);
532
0
  if (unlikely(retcode <= 0))
533
0
    return retcode;
534
535
0
  for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);
536
0
  if (l < *len1 && (*blk1)[l] == '\n') {
537
0
    *len1 = l + 1;
538
0
    return 1;
539
0
  }
540
541
0
  if (retcode >= 2) {
542
0
    for (l = 0; l < *len2 && (*blk2)[l] != '\n'; l++);
543
0
    if (l < *len2 && (*blk2)[l] == '\n') {
544
0
      *len2 = l + 1;
545
0
      return 2;
546
0
    }
547
0
  }
548
549
0
  if (chn_cons(chn)->flags & SC_FL_SHUT_DONE) {
550
    /* If we have found no LF and the buffer is shut, then
551
     * the resulting string is made of the concatenation of
552
     * the pending blocks (1 or 2).
553
     */
554
0
    return retcode;
555
0
  }
556
557
  /* No LF yet and not shut yet */
558
0
  return 0;
559
0
}
560
561
/* Inserts <str> at position <pos> relative to channel <c>'s  * input head. The
562
 * <len> argument informs about the length of string <str> so that we don't have
563
 * to measure it. <str> must be a valid pointer.
564
 *
565
 * The number of bytes added is returned on success. 0 is returned on failure.
566
 */
567
int ci_insert(struct channel *c, int pos, const char *str, int len)
568
0
{
569
0
  struct buffer *b = &c->buf;
570
0
  char *dst = c_ptr(c, pos);
571
572
0
  if (__b_tail(b) + len >= b_wrap(b))
573
0
    return 0;  /* no space left */
574
575
0
  if (b_data(b) &&
576
0
      b_tail(b) + len > b_head(b) &&
577
0
      b_head(b) >= b_tail(b))
578
0
    return 0;  /* no space left before wrapping data */
579
580
  /* first, protect the end of the buffer */
581
0
  memmove(dst + len, dst, b_tail(b) - dst);
582
583
  /* now, copy str over dst */
584
0
  memcpy(dst, str, len);
585
586
0
  b_add(b, len);
587
0
  return len;
588
0
}
589
590
591
/* Inserts <str> followed by "\r\n" at position <pos> relative to channel <c>'s
592
 * input head. The <len> argument informs about the length of string <str> so
593
 * that we don't have to measure it. <str> must be a valid pointer and must not
594
 * include the trailing "\r\n".
595
 *
596
 * The number of bytes added is returned on success. 0 is returned on failure.
597
 */
598
int ci_insert_line2(struct channel *c, int pos, const char *str, int len)
599
0
{
600
0
  struct buffer *b = &c->buf;
601
0
  char *dst = c_ptr(c, pos);
602
0
  int delta;
603
604
0
  delta = len + 2;
605
606
0
  if (__b_tail(b) + delta >= b_wrap(b))
607
0
    return 0;  /* no space left */
608
609
0
  if (b_data(b) &&
610
0
      b_tail(b) + delta > b_head(b) &&
611
0
      b_head(b) >= b_tail(b))
612
0
    return 0;  /* no space left before wrapping data */
613
614
  /* first, protect the end of the buffer */
615
0
  memmove(dst + delta, dst, b_tail(b) - dst);
616
617
  /* now, copy str over dst */
618
0
  memcpy(dst, str, len);
619
0
  dst[len] = '\r';
620
0
  dst[len + 1] = '\n';
621
622
0
  b_add(b, delta);
623
0
  return delta;
624
0
}
625
626
/*
627
 * Local variables:
628
 *  c-indent-level: 8
629
 *  c-basic-offset: 8
630
 * End:
631
 */