Coverage Report

Created: 2026-07-12 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/src/stream.c
Line
Count
Source
1
/*
2
 * Stream management functions.
3
 *
4
 * Copyright 2000-2012 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 <stdlib.h>
14
#include <unistd.h>
15
16
#include <import/ebistree.h>
17
18
#include <haproxy/acl.h>
19
#include <haproxy/action.h>
20
#include <haproxy/activity.h>
21
#include <haproxy/api.h>
22
#include <haproxy/applet.h>
23
#include <haproxy/arg.h>
24
#include <haproxy/backend.h>
25
#include <haproxy/capture.h>
26
#include <haproxy/cfgparse.h>
27
#include <haproxy/channel.h>
28
#include <haproxy/check.h>
29
#include <haproxy/cli.h>
30
#include <haproxy/connection.h>
31
#include <haproxy/dict.h>
32
#include <haproxy/dynbuf.h>
33
#include <haproxy/fd.h>
34
#include <haproxy/filters.h>
35
#include <haproxy/freq_ctr.h>
36
#include <haproxy/frontend.h>
37
#include <haproxy/global.h>
38
#include <haproxy/hlua.h>
39
#include <haproxy/http_ana.h>
40
#include <haproxy/http_rules.h>
41
#include <haproxy/htx.h>
42
#include <haproxy/istbuf.h>
43
#include <haproxy/log.h>
44
#include <haproxy/pipe.h>
45
#include <haproxy/pool.h>
46
#include <haproxy/proxy.h>
47
#include <haproxy/queue.h>
48
#include <haproxy/sc_strm.h>
49
#include <haproxy/server.h>
50
#include <haproxy/resolvers.h>
51
#include <haproxy/sample.h>
52
#include <haproxy/session.h>
53
#include <haproxy/stconn.h>
54
#include <haproxy/stick_table.h>
55
#include <haproxy/stream.h>
56
#include <haproxy/task.h>
57
#include <haproxy/tcp_rules.h>
58
#include <haproxy/thread.h>
59
#include <haproxy/tools.h>
60
#include <haproxy/trace.h>
61
#include <haproxy/vars.h>
62
63
64
DECLARE_TYPED_POOL(pool_head_stream, "stream", struct stream);
65
DECLARE_POOL(pool_head_uniqueid, "uniqueid", UNIQUEID_LEN);
66
67
/* incremented by each "show sess" to fix a delimiter between streams */
68
unsigned stream_epoch = 0;
69
70
/* List of all use-service keywords. */
71
static struct list service_keywords = LIST_HEAD_INIT(service_keywords);
72
73
74
#if defined(USE_TRACE)
75
76
/* trace source and events */
77
static void strm_trace(enum trace_level level, uint64_t mask,
78
           const struct trace_source *src,
79
           const struct ist where, const struct ist func,
80
           const void *a1, const void *a2, const void *a3, const void *a4);
81
82
/* The event representation is split like this :
83
 *   strm  - stream
84
 *   sc    - stream connector
85
 *   http  - http analysis
86
 *   tcp   - tcp analysis
87
 *
88
 * STRM_EV_* macros are defined in <proto/stream.h>
89
 */
90
static const struct trace_event strm_trace_events[] = {
91
  { .mask = STRM_EV_STRM_NEW,     .name = "strm_new",     .desc = "new stream" },
92
  { .mask = STRM_EV_STRM_FREE,    .name = "strm_free",    .desc = "release stream" },
93
  { .mask = STRM_EV_STRM_ERR,     .name = "strm_err",     .desc = "error during stream processing" },
94
  { .mask = STRM_EV_STRM_ANA,     .name = "strm_ana",     .desc = "stream analyzers" },
95
  { .mask = STRM_EV_STRM_PROC,    .name = "strm_proc",    .desc = "stream processing" },
96
97
  { .mask = STRM_EV_CS_ST,        .name = "sc_state",     .desc = "processing connector states" },
98
99
  { .mask = STRM_EV_HTTP_ANA,     .name = "http_ana",     .desc = "HTTP analyzers" },
100
  { .mask = STRM_EV_HTTP_ERR,     .name = "http_err",     .desc = "error during HTTP analysis" },
101
102
  { .mask = STRM_EV_TCP_ANA,      .name = "tcp_ana",      .desc = "TCP analyzers" },
103
  { .mask = STRM_EV_TCP_ERR,      .name = "tcp_err",      .desc = "error during TCP analysis" },
104
105
  { .mask = STRM_EV_FLT_ANA,      .name = "flt_ana",      .desc = "Filter analyzers" },
106
  { .mask = STRM_EV_FLT_ERR,      .name = "flt_err",      .desc = "error during filter analysis" },
107
  {}
108
};
109
110
static const struct name_desc strm_trace_lockon_args[4] = {
111
  /* arg1 */ { /* already used by the stream */ },
112
  /* arg2 */ { },
113
  /* arg3 */ { },
114
  /* arg4 */ { }
115
};
116
117
static const struct name_desc strm_trace_decoding[] = {
118
0
#define STRM_VERB_CLEAN    1
119
  { .name="clean",    .desc="only user-friendly stuff, generally suitable for level \"user\"" },
120
0
#define STRM_VERB_MINIMAL  2
121
  { .name="minimal",  .desc="report info on streams and connectors" },
122
0
#define STRM_VERB_SIMPLE   3
123
  { .name="simple",   .desc="add info on request and response channels" },
124
0
#define STRM_VERB_ADVANCED 4
125
  { .name="advanced", .desc="add info on channel's buffer for data and developer levels only" },
126
0
#define STRM_VERB_COMPLETE 5
127
  { .name="complete", .desc="add info on channel's buffer" },
128
  { /* end */ }
129
};
130
131
struct trace_source trace_strm = {
132
  .name = IST("stream"),
133
  .desc = "Applicative stream",
134
  .arg_def = TRC_ARG1_STRM,  // TRACE()'s first argument is always a stream
135
  .default_cb = strm_trace,
136
  .known_events = strm_trace_events,
137
  .lockon_args = strm_trace_lockon_args,
138
  .decoding = strm_trace_decoding,
139
  .report_events = ~0,  // report everything by default
140
};
141
142
#define TRACE_SOURCE &trace_strm
143
INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
144
145
/* the stream traces always expect that arg1, if non-null, is of a stream (from
146
 * which we can derive everything), that arg2, if non-null, is an http
147
 * transaction, that arg3, if non-null, is an http message.
148
 */
149
static void strm_trace(enum trace_level level, uint64_t mask, const struct trace_source *src,
150
           const struct ist where, const struct ist func,
151
           const void *a1, const void *a2, const void *a3, const void *a4)
152
0
{
153
0
  const struct stream *s = a1;
154
0
  const struct http_txn *txn = a2;
155
0
  const struct http_msg *msg = a3;
156
0
  struct task *task;
157
0
  const struct channel *req, *res;
158
0
  struct htx *htx;
159
160
0
  if (!s || src->verbosity < STRM_VERB_CLEAN)
161
0
    return;
162
163
0
  task = s->task;
164
0
  req  = &s->req;
165
0
  res  = &s->res;
166
0
  htx  = (msg ? htxbuf(&msg->chn->buf) : NULL);
167
168
  /* General info about the stream (htx/tcp, id...) */
169
0
  chunk_appendf(&trace_buf, " : [%u,%s]",
170
0
          s->uniq_id, ((s->flags & SF_HTX) ? "HTX" : "TCP"));
171
0
  if (isttest(s->unique_id)) {
172
0
    chunk_appendf(&trace_buf, " id=");
173
0
    b_putist(&trace_buf, s->unique_id);
174
0
  }
175
176
  /* Front and back stream connector state */
177
0
  chunk_appendf(&trace_buf, " SC=(%s,%s)",
178
0
          sc_state_str(s->scf->state), sc_state_str(s->scb->state));
179
180
  /* If txn is defined, HTTP req/rep states */
181
0
  if (txn)
182
0
    chunk_appendf(&trace_buf, " HTTP=(%s,%s)",
183
0
            h1_msg_state_str(txn->req.msg_state), h1_msg_state_str(txn->rsp.msg_state));
184
0
  if (msg)
185
0
    chunk_appendf(&trace_buf, " %s", ((msg->chn->flags & CF_ISRESP) ? "RESPONSE" : "REQUEST"));
186
187
0
  if (src->verbosity == STRM_VERB_CLEAN)
188
0
    return;
189
190
  /* If msg defined, display status-line if possible (verbosity > MINIMAL) */
191
0
  if (src->verbosity > STRM_VERB_MINIMAL && htx && htx_nbblks(htx)) {
192
0
    const struct htx_blk *blk = __htx_get_head_blk(htx);
193
0
    const struct htx_sl  *sl  = htx_get_blk_ptr(htx, blk);
194
0
    enum htx_blk_type    type = htx_get_blk_type(blk);
195
196
0
    if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL)
197
0
      chunk_appendf(&trace_buf, " - \"%.*s %.*s %.*s\"",
198
0
              HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl),
199
0
              HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl),
200
0
              HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
201
0
  }
202
203
0
    chunk_appendf(&trace_buf, " - t=%p t.exp=%d s=(%p,0x%08x,0x%x)",
204
0
            task, tick_isset(task->expire) ? TICKS_TO_MS(task->expire - now_ms) : TICK_ETERNITY, s, s->flags, s->conn_err_type);
205
206
  /* If txn defined info about HTTP msgs, otherwise info about SI. */
207
0
  if (txn) {
208
0
    chunk_appendf(&trace_buf, " txn.flags=0x%08x, http.flags=(0x%08x,0x%08x) status=%d",
209
0
            txn->flags, txn->req.flags, txn->rsp.flags, txn->status);
210
0
  }
211
0
  else {
212
0
    chunk_appendf(&trace_buf, " scf=(%p,%d,0x%08x,0x%x) scb=(%p,%d,0x%08x,0x%x) scf.exp(r,w)=(%d,%d) scb.exp(r,w)=(%d,%d) retries=%d",
213
0
            s->scf, s->scf->state, s->scf->flags, s->scf->sedesc->flags,
214
0
            s->scb, s->scb->state, s->scb->flags, s->scb->sedesc->flags,
215
0
            tick_isset(sc_ep_rcv_ex(s->scf)) ? TICKS_TO_MS(sc_ep_rcv_ex(s->scf) - now_ms) : TICK_ETERNITY,
216
0
            tick_isset(sc_ep_snd_ex(s->scf)) ? TICKS_TO_MS(sc_ep_snd_ex(s->scf) - now_ms) : TICK_ETERNITY,
217
0
            tick_isset(sc_ep_rcv_ex(s->scb)) ? TICKS_TO_MS(sc_ep_rcv_ex(s->scb) - now_ms) : TICK_ETERNITY,
218
0
            tick_isset(sc_ep_snd_ex(s->scb)) ? TICKS_TO_MS(sc_ep_snd_ex(s->scb) - now_ms) : TICK_ETERNITY,
219
0
            s->conn_retries);
220
0
  }
221
222
0
  if (src->verbosity == STRM_VERB_MINIMAL)
223
0
    return;
224
225
226
  /* If txn defined, don't display all channel info */
227
0
  if (src->verbosity == STRM_VERB_SIMPLE || txn) {
228
0
    chunk_appendf(&trace_buf, " req=(%p .fl=0x%08x .exp=%d)",
229
0
            req, req->flags, tick_isset(req->analyse_exp) ? TICKS_TO_MS(req->analyse_exp - now_ms) : TICK_ETERNITY);
230
0
    chunk_appendf(&trace_buf, " res=(%p .fl=0x%08x .exp=%d)",
231
0
            res, res->flags, tick_isset(res->analyse_exp) ? TICKS_TO_MS(res->analyse_exp - now_ms) : TICK_ETERNITY);
232
0
  }
233
0
  else {
234
0
    chunk_appendf(&trace_buf, " req=(%p .fl=0x%08x .ana=0x%08x .exp=%u .o=%lu .to_fwd=%u)",
235
0
            req, req->flags, req->analysers, req->analyse_exp,
236
0
            (long)req->output, req->to_forward);
237
0
    chunk_appendf(&trace_buf, " res=(%p .fl=0x%08x .ana=0x%08x .exp=%u .o=%lu .to_fwd=%u)",
238
0
            res, res->flags, res->analysers, res->analyse_exp,
239
0
            (long)res->output, res->to_forward);
240
0
  }
241
242
0
  if (src->verbosity == STRM_VERB_SIMPLE ||
243
0
      (src->verbosity == STRM_VERB_ADVANCED && src->level < TRACE_LEVEL_DATA))
244
0
    return;
245
246
  /* channels' buffer info */
247
0
  if (s->flags & SF_HTX) {
248
0
    struct htx *rqhtx = htxbuf(&req->buf);
249
0
    struct htx *rphtx = htxbuf(&res->buf);
250
251
0
    chunk_appendf(&trace_buf, " htx=(%u/%u#%u, %u/%u#%u)",
252
0
            rqhtx->data, rqhtx->size, htx_nbblks(rqhtx),
253
0
            rphtx->data, rphtx->size, htx_nbblks(rphtx));
254
0
  }
255
0
  else {
256
0
    chunk_appendf(&trace_buf, " buf=(%u@%p+%u/%u, %u@%p+%u/%u)",
257
0
            (unsigned int)b_data(&req->buf), b_orig(&req->buf),
258
0
            (unsigned int)b_head_ofs(&req->buf), (unsigned int)b_size(&req->buf),
259
0
            (unsigned int)b_data(&res->buf), b_orig(&res->buf),
260
0
            (unsigned int)b_head_ofs(&res->buf), (unsigned int)b_size(&res->buf));
261
0
  }
262
263
  /* If msg defined, display htx info if defined (level > USER) */
264
0
  if (src->level > TRACE_LEVEL_USER && htx && htx_nbblks(htx)) {
265
0
    int full = 0;
266
267
    /* Full htx info (level > STATE && verbosity > SIMPLE) */
268
0
    if (src->level > TRACE_LEVEL_STATE) {
269
0
      if (src->verbosity == STRM_VERB_COMPLETE)
270
0
        full = 1;
271
0
    }
272
273
0
    chunk_memcat(&trace_buf, "\n\t", 2);
274
0
    htx_dump(&trace_buf, htx, full);
275
0
  }
276
0
}
277
#endif
278
279
/* Upgrade an existing stream for stream connector <sc>. Return < 0 on error. This
280
 * is only valid right after a TCP to H1 upgrade. The stream should be
281
 * "reativated" by removing SF_IGNORE flag. And the right mode must be set.  On
282
 * success, <input> buffer is transferred to the stream and thus points to
283
 * BUF_NULL. On error, it is unchanged and it is the caller responsibility to
284
 * release it (this never happens for now).
285
 */
286
int stream_upgrade_from_sc(struct stconn *sc, struct buffer *input)
287
0
{
288
0
  struct stream *s = __sc_strm(sc);
289
0
  const struct mux_ops *mux = sc_mux_ops(sc);
290
291
0
  if (mux) {
292
0
    if (mux->flags & MX_FL_HTX)
293
0
      s->flags |= SF_HTX;
294
0
  }
295
296
0
  if (!b_is_null(input)) {
297
    /* Xfer the input buffer to the request channel. <input> will
298
     * than point to BUF_NULL. From this point, it is the stream
299
     * responsibility to release it.
300
     */
301
0
    s->req.buf = *input;
302
0
    *input = BUF_NULL;
303
0
    s->scf->bytes_in = (IS_HTX_STRM(s) ? htxbuf(&s->req.buf)->data : b_data(&s->req.buf));
304
0
    sc_ep_report_read_activity(s->scf);
305
0
  }
306
307
0
  s->req.flags |= CF_READ_EVENT; /* Always report a read event */
308
0
  s->flags &= ~SF_IGNORE;
309
310
0
  task_wakeup(s->task, TASK_WOKEN_INIT);
311
0
  return 0;
312
0
}
313
314
/* Callback used to wake up a stream when an input buffer is available. The
315
 * stream <s>'s stream connectors are checked for a failed buffer allocation
316
 * as indicated by the presence of the SC_FL_NEED_BUFF flag and the lack of a
317
 * buffer, and and input buffer is assigned there (at most one). The function
318
 * returns 1 and wakes the stream up if a buffer was taken, otherwise zero.
319
 * It's designed to be called from __offer_buffer().
320
 */
321
int stream_buf_available(void *arg)
322
0
{
323
0
  struct stream *s = arg;
324
325
0
  if (!s->req.buf.size && !sc_ep_have_ff_data(s->scb) && s->scf->flags & SC_FL_NEED_BUFF)
326
0
    sc_have_buff(s->scf);
327
328
0
  if (!s->res.buf.size && !sc_ep_have_ff_data(s->scf) && s->scb->flags & SC_FL_NEED_BUFF)
329
0
    sc_have_buff(s->scb);
330
331
0
  s->flags |= SF_MAYALLOC;
332
0
  task_wakeup(s->task, TASK_WOKEN_RES);
333
0
  return 1;
334
335
0
}
336
337
/* This function is called from the session handler which detects the end of
338
 * handshake, in order to complete initialization of a valid stream. It must be
339
 * called with a completely initialized session. It returns the pointer to
340
 * the newly created stream, or NULL in case of fatal error. The client-facing
341
 * end point is assigned to <origin>, which must be valid. The stream's task
342
 * is configured with a nice value inherited from the listener's nice if any.
343
 * The task's context is set to the new stream, and its function is set to
344
 * process_stream(). Target and analysers are null. <input> is used as input
345
 * buffer for the request channel and may contain data. On success, it is
346
 * transfer to the stream and <input> is set to BUF_NULL. On error, <input>
347
 * buffer is unchanged and it is the caller responsibility to release it.
348
 */
349
void *stream_new(struct session *sess, struct stconn *sc, struct buffer *input)
350
0
{
351
0
  struct stream *s;
352
0
  struct task *t;
353
354
0
  DBG_TRACE_ENTER(STRM_EV_STRM_NEW);
355
0
  if (unlikely((s = pool_alloc(pool_head_stream)) == NULL))
356
0
    goto out_fail_alloc;
357
358
  /* minimum stream initialization required for an embryonic stream is
359
   * fairly low. We need very little to execute L4 ACLs, then we need a
360
   * task to make the client-side connection live on its own.
361
   *  - flags
362
   *  - stick-entry tracking
363
   */
364
0
  s->flags = 0;
365
0
  s->logs.logwait = sess->fe->to_log;
366
0
  s->logs.level = 0;
367
0
  s->logs.request_ts = 0;
368
0
  s->logs.t_queue = -1;
369
0
  s->logs.t_connect = -1;
370
0
  s->logs.t_data = -1;
371
0
  s->logs.t_close = 0;
372
0
  s->logs.req_in = s->logs.req_out = 0;
373
0
  s->logs.res_in = s->logs.res_out = 0;
374
0
  s->logs.prx_queue_pos = 0;  /* we get the number of pending conns before us */
375
0
  s->logs.srv_queue_pos = 0; /* we will get this number soon */
376
0
  s->obj_type = OBJ_TYPE_STREAM;
377
378
0
  s->logs.accept_date = sess->accept_date;
379
0
  s->logs.accept_ts = sess->accept_ts;
380
0
  s->logs.t_handshake = sess->t_handshake;
381
0
  s->logs.t_idle = sess->t_idle;
382
383
  /* default logging function */
384
0
  s->do_log = strm_log;
385
386
  /* default error reporting function, may be changed by analysers */
387
0
  s->srv_error = default_srv_error;
388
389
  /* Initialise the current rule list pointer to NULL. We are sure that
390
   * any rulelist match the NULL pointer.
391
   */
392
0
  s->current_rule_list = NULL;
393
0
  s->current_rule = NULL;
394
0
  s->rules_exp = TICK_ETERNITY;
395
0
  s->last_entity.type = STRM_ENTITY_NONE;
396
0
  s->last_entity.ptr = NULL;
397
0
  s->waiting_entity.type = STRM_ENTITY_NONE;
398
0
  s->waiting_entity.ptr = NULL;
399
400
0
  s->stkctr = NULL;
401
0
  if (pool_head_stk_ctr) {
402
0
    s->stkctr = pool_alloc(pool_head_stk_ctr);
403
0
    if (!s->stkctr)
404
0
      goto out_fail_alloc;
405
406
    /* Copy SC counters for the stream. We don't touch refcounts because
407
     * any reference we have is inherited from the session. Since the stream
408
     * doesn't exist without the session, the session's existence guarantees
409
     * we don't lose the entry. During the store operation, the stream won't
410
     * touch these ones.
411
     */
412
0
    memcpy(s->stkctr, sess->stkctr, sizeof(s->stkctr[0]) * global.tune.nb_stk_ctr);
413
0
  }
414
415
0
  s->sess = sess;
416
417
0
  s->stream_epoch = _HA_ATOMIC_LOAD(&stream_epoch);
418
0
  s->uniq_id = _HA_ATOMIC_FETCH_ADD(&global.req_count, 1);
419
0
  s->term_evts_log = 0;
420
421
  /* OK, we're keeping the stream, so let's properly initialize the stream */
422
0
  LIST_INIT(&s->back_refs);
423
424
0
  LIST_INIT(&s->buffer_wait.list);
425
0
  s->buffer_wait.target = s;
426
0
  s->buffer_wait.wakeup_cb = stream_buf_available;
427
428
0
  s->lat_time = s->cpu_time = 0;
429
0
  s->call_rate.curr_tick = s->call_rate.curr_ctr = s->call_rate.prev_ctr = 0;
430
0
  s->passes_connect = s->passes_stconn = s->passes_reqana = s->passes_resana = s->passes_propag = 0;
431
0
  s->unique_id = IST_NULL;
432
0
  s->parent = NULL;
433
0
  if ((t = task_new_here()) == NULL)
434
0
    goto out_fail_alloc;
435
436
0
  s->task = t;
437
0
  s->pending_events = s->new_events = STRM_EVT_NONE;
438
0
  s->conn_retries = 0;
439
0
  s->max_retries = ((sess->fe->cap & PR_CAP_BE) ? sess->fe->conn_retries : 0);
440
0
  s->conn_exp = TICK_ETERNITY;
441
0
  s->conn_err_type = STRM_ET_NONE;
442
0
  s->prev_conn_state = SC_ST_INI;
443
0
  t->process = process_stream;
444
0
  t->context = s;
445
0
  t->expire = TICK_ETERNITY;
446
0
  if (sess->listener)
447
0
    t->nice = sess->listener->bind_conf->nice;
448
449
  /* Note: initially, the stream's backend points to the frontend.
450
   * This changes later when switching rules are executed or
451
   * when the default backend is assigned.
452
   */
453
0
  s->be  = sess->fe;
454
0
  if (sess->fe->be_counters.shared.tg)
455
0
    s->be_tgcounters = sess->fe->be_counters.shared.tg[tgid - 1];
456
0
  else
457
0
    s->be_tgcounters = NULL;
458
459
0
  s->sv_tgcounters = NULL; // default value
460
461
0
  s->req_cap = NULL;
462
0
  s->res_cap = NULL;
463
464
  /* Initialize all the variables contexts even if not used.
465
   * This permits to prune these contexts without errors.
466
   *
467
   * We need to make sure that those lists are not re-initialized
468
   * by stream-dependant underlying code because we could lose
469
   * track of already defined variables, leading to data inconsistency
470
   * and memory leaks...
471
   *
472
   * For reference: we had a very old bug caused by vars_txn and
473
   * vars_reqres being accidentally re-initialized in http_create_txn()
474
   * (https://github.com/haproxy/haproxy/issues/1935)
475
   */
476
0
  vars_init_head(&s->vars_txn,    SCOPE_TXN);
477
0
  vars_init_head(&s->vars_reqres, SCOPE_REQ);
478
479
        /* Set SF_HTX flag for HTTP frontends. */
480
0
  if (sess->fe->mode == PR_MODE_HTTP)
481
0
    s->flags |= SF_HTX;
482
483
0
  s->scf = sc;
484
0
  if (sc_attach_strm(s->scf, s) < 0)
485
0
    goto out_fail_attach_scf;
486
487
0
  s->scb = sc_new_from_strm(s, SC_FL_ISBACK);
488
0
  if (!s->scb)
489
0
    goto out_fail_alloc_scb;
490
491
0
  sc_set_state(s->scf, SC_ST_EST);
492
493
0
  if (likely(sess->fe->options2 & PR_O2_INDEPSTR))
494
0
    s->scf->flags |= SC_FL_INDEP_STR;
495
496
0
  if (likely(sess->fe->options2 & PR_O2_INDEPSTR))
497
0
    s->scb->flags |= SC_FL_INDEP_STR;
498
499
0
  if (sc_ep_test(sc, SE_FL_WEBSOCKET))
500
0
    s->flags |= SF_WEBSOCKET;
501
0
  if (sc_conn(sc)) {
502
0
    const struct mux_ops *mux = sc_mux_ops(sc);
503
504
0
    if (mux && mux->flags & MX_FL_HTX)
505
0
      s->flags |= SF_HTX;
506
0
  }
507
508
0
  stream_init_srv_conn(s);
509
0
  s->target = sess->fe->default_target;
510
511
0
  s->pend_pos = NULL;
512
0
  s->priority_class = 0;
513
0
  s->priority_offset = 0;
514
515
  /* init store persistence */
516
0
  s->store_count = 0;
517
518
0
  channel_init(&s->req);
519
0
  s->req.flags |= CF_READ_EVENT; /* the producer is already connected */
520
0
  s->req.analysers = sess->listener ? sess->listener->bind_conf->analysers : sess->fe->fe_req_ana;
521
522
0
  if (IS_HTX_STRM(s)) {
523
    /* Be sure to have HTTP analysers because in case of
524
     * "destructive" stream upgrade, they may be missing (e.g
525
     * TCP>H2)
526
     */
527
0
    s->req.analysers |= AN_REQ_WAIT_HTTP|AN_REQ_HTTP_PROCESS_FE;
528
0
  }
529
530
0
  if (!sess->fe->fe_req_ana) {
531
0
    channel_auto_connect(&s->req);  /* don't wait to establish connection */
532
0
    channel_auto_close(&s->req);    /* let the producer forward close requests */
533
0
  }
534
535
0
  s->scf->ioto = sess->fe->timeout.client;
536
0
  s->req.analyse_exp = TICK_ETERNITY;
537
538
0
  channel_init(&s->res);
539
0
  s->res.flags |= CF_ISRESP;
540
0
  s->res.analysers = 0;
541
542
0
  if (sess->fe->options2 & PR_O2_NODELAY) {
543
0
    s->scf->flags |= SC_FL_SND_NEVERWAIT;
544
0
    s->scb->flags |= SC_FL_SND_NEVERWAIT;
545
0
  }
546
547
0
  s->scb->ioto = TICK_ETERNITY;
548
0
  s->res.analyse_exp = TICK_ETERNITY;
549
550
0
  s->txn.http = NULL;
551
0
  s->hlua[0] = s->hlua[1] = NULL;
552
553
0
  s->resolv_ctx.requester = NULL;
554
0
  s->resolv_ctx.hostname_dn = NULL;
555
0
  s->resolv_ctx.hostname_dn_len = 0;
556
0
  s->resolv_ctx.parent = NULL;
557
558
0
  s->connect_timeout = TICK_ETERNITY;
559
0
  s->queue_timeout = TICK_ETERNITY;
560
0
  s->tarpit_timeout = TICK_ETERNITY;
561
0
  s->tunnel_timeout = TICK_ETERNITY;
562
563
0
  LIST_APPEND(&th_ctx->streams, &s->list);
564
0
  _HA_ATOMIC_INC(&th_ctx->total_streams);
565
0
  _HA_ATOMIC_INC(&th_ctx->stream_cnt);
566
567
0
  if (flt_stream_init(s) < 0 || flt_stream_start(s) < 0)
568
0
    goto out_fail_accept;
569
570
  /* just in case the caller would have pre-disabled it */
571
0
  se_will_consume(s->scf->sedesc);
572
573
0
  if (sess->fe->accept && sess->fe->accept(s) < 0)
574
0
    goto out_fail_accept;
575
576
0
  if (!b_is_null(input)) {
577
    /* Xfer the input buffer to the request channel. <input> will
578
     * than point to BUF_NULL. From this point, it is the stream
579
     * responsibility to release it.
580
     */
581
0
    s->req.buf = *input;
582
0
    *input = BUF_NULL;
583
0
    s->scf->bytes_in = (IS_HTX_STRM(s) ? htxbuf(&s->req.buf)->data : b_data(&s->req.buf));
584
0
    sc_ep_report_read_activity(s->scf);
585
0
  }
586
587
  /* it is important not to call the wakeup function directly but to
588
   * pass through task_wakeup(), because this one knows how to apply
589
   * priorities to tasks. Using multi thread we must be sure that
590
   * stream is fully initialized before calling task_wakeup. So
591
   * the caller must handle the task_wakeup
592
   */
593
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_NEW, s);
594
0
  task_wakeup(s->task, TASK_WOKEN_INIT);
595
0
  return s;
596
597
  /* Error unrolling */
598
0
 out_fail_accept:
599
0
  flt_stream_release(s, 0);
600
0
  LIST_DELETE(&s->list);
601
0
  sc_free(s->scb);
602
0
 out_fail_alloc_scb:
603
0
 out_fail_attach_scf:
604
0
  task_destroy(t);
605
0
 out_fail_alloc:
606
0
  if (s)
607
0
    pool_free(pool_head_stk_ctr, s->stkctr);
608
0
  pool_free(pool_head_stream, s);
609
0
  DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_NEW|STRM_EV_STRM_ERR);
610
0
  return NULL;
611
0
}
612
613
/*
614
 * frees  the context associated to a stream. It must have been removed first.
615
 */
616
void stream_free(struct stream *s)
617
0
{
618
0
  struct session *sess = strm_sess(s);
619
0
  struct proxy *fe = sess->fe;
620
0
  struct bref *bref, *back;
621
0
  int i;
622
623
0
  DBG_TRACE_POINT(STRM_EV_STRM_FREE, s);
624
625
  /* detach the stream from its own task before even releasing it so
626
   * that walking over a task list never exhibits a dying stream.
627
   */
628
0
  s->task->context = NULL;
629
0
  __ha_barrier_store();
630
631
0
  pendconn_free(s);
632
633
0
  if (objt_server(s->target)) { /* there may be requests left pending in queue */
634
0
    if (s->flags & SF_CURR_SESS) {
635
0
      s->flags &= ~SF_CURR_SESS;
636
0
      _HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
637
0
    }
638
0
    if (may_dequeue_tasks(__objt_server(s->target), s->be))
639
0
      process_srv_queue(__objt_server(s->target));
640
0
  }
641
642
0
  if (unlikely(s->srv_conn)) {
643
0
    struct server *oldsrv = s->srv_conn;
644
    /* the stream still has a reserved slot on a server, but
645
     * it should normally be only the same as the one above,
646
     * so this should not happen in fact.
647
     */
648
    /*
649
     * We don't want to release the slot just yet
650
     * if we're using strict-maxconn, we want to
651
     * free the connection before.
652
     */
653
0
    if (!(oldsrv->flags & SRV_F_STRICT_MAXCONN)) {
654
0
      sess_change_server(s, NULL);
655
0
      if (may_dequeue_tasks(oldsrv, s->be))
656
0
        process_srv_queue(oldsrv);
657
0
    }
658
0
  }
659
660
  /* We may still be present in the buffer wait queue */
661
0
  b_dequeue(&s->buffer_wait);
662
663
0
  if (s->req.buf.size || s->res.buf.size) {
664
0
    int count = 0;
665
666
0
    if (b_is_default(&s->req.buf))
667
0
      count++;
668
0
    if (b_is_default(&s->res.buf))
669
0
      count++;
670
671
0
    b_free(&s->req.buf);
672
0
    b_free(&s->res.buf);
673
0
    if (count)
674
0
      offer_buffers(NULL, count);
675
0
  }
676
677
0
  pool_free(pool_head_uniqueid, s->unique_id.ptr);
678
0
  s->unique_id = IST_NULL;
679
680
0
  flt_stream_stop(s);
681
0
  flt_stream_release(s, 0);
682
683
0
  hlua_ctx_destroy(s->hlua[0]);
684
0
  hlua_ctx_destroy(s->hlua[1]);
685
0
  s->hlua[0] = s->hlua[1] = NULL;
686
687
0
  if ((s->flags & SF_TXN_MASK) == SF_TXN_HTTP)
688
0
    http_destroy_txn(s);
689
0
  else if ((s->flags & SF_TXN_MASK) == SF_TXN_PCLI)
690
0
    pcli_destroy_txn(s);
691
692
  /* ensure the client-side transport layer is destroyed */
693
  /* Be sure it is useless !! */
694
  /* if (cli_cs) */
695
  /*  cs_close(cli_cs); */
696
697
0
  for (i = 0; i < s->store_count; i++) {
698
0
    if (!s->store[i].ts)
699
0
      continue;
700
0
    stksess_free(s->store[i].table, s->store[i].ts);
701
0
    s->store[i].ts = NULL;
702
0
  }
703
704
0
  if (s->resolv_ctx.requester) {
705
0
    __decl_thread(struct resolvers *resolvers = s->resolv_ctx.parent->arg.resolv.resolvers);
706
707
0
    HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
708
0
    ha_free(&s->resolv_ctx.hostname_dn);
709
0
    s->resolv_ctx.hostname_dn_len = 0;
710
0
    resolv_unlink_resolution(s->resolv_ctx.requester);
711
0
    HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
712
713
0
    pool_free(resolv_requester_pool, s->resolv_ctx.requester);
714
0
    s->resolv_ctx.requester = NULL;
715
0
  }
716
717
0
  if (fe) {
718
0
    if (s->req_cap) {
719
0
      struct cap_hdr *h;
720
0
      for (h = fe->req_cap; h; h = h->next)
721
0
        pool_free(h->pool, s->req_cap[h->index]);
722
0
      pool_free(fe->req_cap_pool, s->req_cap);
723
0
    }
724
725
0
    if (s->res_cap) {
726
0
      struct cap_hdr *h;
727
0
      for (h = fe->rsp_cap; h; h = h->next)
728
0
        pool_free(h->pool, s->res_cap[h->index]);
729
0
      pool_free(fe->rsp_cap_pool, s->res_cap);
730
0
    }
731
0
  }
732
733
  /* Cleanup all variable contexts. */
734
0
  vars_prune(&s->vars_txn, s->sess, s);
735
0
  vars_prune(&s->vars_reqres, s->sess, s);
736
737
0
  stream_store_counters(s);
738
0
  pool_free(pool_head_stk_ctr, s->stkctr);
739
740
0
  list_for_each_entry_safe(bref, back, &s->back_refs, users) {
741
    /* we have to unlink all watchers. We must not relink them if
742
     * this stream was the last one in the list. This is safe to do
743
     * here because we're touching our thread's list so we know
744
     * that other streams are not active, and the watchers will
745
     * only touch their node under thread isolation.
746
     */
747
0
    LIST_DEL_INIT(&bref->users);
748
0
    if (s->list.n != &th_ctx->streams)
749
0
      LIST_APPEND(&LIST_ELEM(s->list.n, struct stream *, list)->back_refs, &bref->users);
750
0
    bref->ref = s->list.n;
751
0
    __ha_barrier_store();
752
0
  }
753
0
  LIST_DELETE(&s->list);
754
0
  _HA_ATOMIC_DEC(&th_ctx->stream_cnt);
755
756
0
  sc_destroy(s->scb);
757
0
  sc_destroy(s->scf);
758
  /*
759
   * Now we've free'd the connection, so if we're running with
760
   * strict-maxconn, now is a good time to free the slot, and see
761
   * if we can dequeue anything.
762
   */
763
0
  if (s->srv_conn && (s->srv_conn->flags & SRV_F_STRICT_MAXCONN)) {
764
0
    struct server *oldsrv = s->srv_conn;
765
766
0
    if ((oldsrv->flags & SRV_F_STRICT_MAXCONN)) {
767
0
      sess_change_server(s, NULL);
768
0
      if (may_dequeue_tasks(oldsrv, s->be))
769
0
        process_srv_queue(oldsrv);
770
0
    }
771
0
  }
772
773
0
  pool_free(pool_head_stream, s);
774
775
  /* We may want to free the maximum amount of pools if the proxy is stopping */
776
0
  if (fe && unlikely(fe->flags & (PR_FL_DISABLED|PR_FL_STOPPED))) {
777
0
    pool_flush(pool_head_buffer);
778
0
    pool_flush(pool_head_large_buffer);
779
0
    pool_flush(pool_head_http_txn);
780
0
    pool_flush(pool_head_pcli_txn);
781
0
    pool_flush(pool_head_requri);
782
0
    pool_flush(pool_head_capture);
783
0
    pool_flush(pool_head_stream);
784
0
    pool_flush(pool_head_session);
785
0
    pool_flush(pool_head_connection);
786
0
    pool_flush(pool_head_pendconn);
787
0
    pool_flush(fe->req_cap_pool);
788
0
    pool_flush(fe->rsp_cap_pool);
789
0
  }
790
0
}
791
792
793
/* Allocates a work buffer for stream <s>. It is meant to be called inside
794
 * process_stream(). It will only allocate the side needed for the function
795
 * to work fine, which is the response buffer so that an error message may be
796
 * built and returned. Response buffers may be allocated from the reserve, this
797
 * is critical to ensure that a response may always flow and will never block a
798
 * server from releasing a connection. Returns 0 in case of failure, non-zero
799
 * otherwise.
800
 */
801
static int stream_alloc_work_buffer(struct stream *s)
802
0
{
803
0
  if (b_alloc(&s->res.buf, DB_CHANNEL | ((s->flags & SF_MAYALLOC) ? DB_F_NOQUEUE : 0))) {
804
0
    s->flags &= ~SF_MAYALLOC;
805
0
    return 1;
806
0
  }
807
808
0
  b_requeue(DB_CHANNEL, &s->buffer_wait);
809
0
  return 0;
810
0
}
811
812
/* releases unused buffers after processing. Typically used at the end of the
813
 * update() functions. It will try to wake up as many tasks/applets as the
814
 * number of buffers that it releases. In practice, most often streams are
815
 * blocked on a single buffer, so it makes sense to try to wake two up when two
816
 * buffers are released at once.
817
 */
818
void stream_release_buffers(struct stream *s)
819
0
{
820
0
  int offer = 0;
821
822
0
  if (c_size(&s->req) && c_empty(&s->req)) {
823
0
    if (b_is_default(&s->req.buf))
824
0
      offer++;
825
0
    b_free(&s->req.buf);
826
0
  }
827
0
  if (c_size(&s->res) && c_empty(&s->res)) {
828
0
    if (b_is_default(&s->res.buf))
829
0
      offer++;
830
0
    b_free(&s->res.buf);
831
0
  }
832
833
  /* if we're certain to have at least 1 buffer available, and there is
834
   * someone waiting, we can wake up a waiter and offer them.
835
   */
836
0
  if (offer)
837
0
    offer_buffers(s, offer);
838
0
}
839
840
void stream_process_counters(struct stream *s)
841
0
{
842
0
  struct session *sess = s->sess;
843
0
  unsigned long long bytes;
844
0
  int i;
845
846
0
  bytes = s->scf->bytes_in - s->logs.req_in;
847
0
  s->logs.req_in = s->scf->bytes_in;
848
0
  if (bytes) {
849
0
    if (sess->fe_tgcounters)
850
0
      _HA_ATOMIC_ADD(&sess->fe_tgcounters->req_in, bytes);
851
0
    if (s->be_tgcounters)
852
0
      _HA_ATOMIC_ADD(&s->be_tgcounters->req_in, bytes);
853
854
0
    if (s->sv_tgcounters)
855
0
      _HA_ATOMIC_ADD(&s->sv_tgcounters->req_in, bytes);
856
857
0
    if (sess->li_tgcounters)
858
0
      _HA_ATOMIC_ADD(&sess->li_tgcounters->req_in, bytes);
859
860
0
    for (i = 0; i < global.tune.nb_stk_ctr; i++) {
861
0
      if (!stkctr_inc_bytes_in_ctr(&s->stkctr[i], bytes))
862
0
        stkctr_inc_bytes_in_ctr(&sess->stkctr[i], bytes);
863
0
    }
864
0
  }
865
866
0
  bytes = s->scb->bytes_out - s->logs.req_out;
867
0
  s->logs.req_out = s->scb->bytes_out;
868
0
  if (bytes) {
869
0
    if (sess->fe_tgcounters)
870
0
      _HA_ATOMIC_ADD(&sess->fe_tgcounters->req_out, bytes);
871
0
    if (s->be_tgcounters)
872
0
      _HA_ATOMIC_ADD(&s->be_tgcounters->req_out, bytes);
873
874
0
    if (s->sv_tgcounters)
875
0
      _HA_ATOMIC_ADD(&s->sv_tgcounters->req_out, bytes);
876
877
0
    if (sess->li_tgcounters)
878
0
      _HA_ATOMIC_ADD(&sess->li_tgcounters->req_out, bytes);
879
0
  }
880
881
0
  bytes = s->scb->bytes_in - s->logs.res_in;
882
0
  s->logs.res_in = s->scb->bytes_in;
883
0
  if (bytes) {
884
0
    if (sess->fe_tgcounters)
885
0
      _HA_ATOMIC_ADD(&sess->fe_tgcounters->res_in, bytes);
886
0
    if (s->be_tgcounters)
887
0
      _HA_ATOMIC_ADD(&s->be_tgcounters->res_in, bytes);
888
889
0
    if (s->sv_tgcounters)
890
0
      _HA_ATOMIC_ADD(&s->sv_tgcounters->res_in, bytes);
891
892
0
    if (sess->li_tgcounters)
893
0
      _HA_ATOMIC_ADD(&sess->li_tgcounters->res_in, bytes);
894
895
0
    for (i = 0; i < global.tune.nb_stk_ctr; i++) {
896
0
      if (!stkctr_inc_bytes_out_ctr(&s->stkctr[i], bytes))
897
0
        stkctr_inc_bytes_out_ctr(&sess->stkctr[i], bytes);
898
0
    }
899
0
  }
900
901
0
  bytes = s->scf->bytes_out - s->logs.res_out;
902
0
  s->logs.res_out = s->scf->bytes_out;
903
0
  if (bytes) {
904
0
    if (sess->fe_tgcounters)
905
0
      _HA_ATOMIC_ADD(&sess->fe_tgcounters->res_out, bytes);
906
0
    if (s->be_tgcounters)
907
0
      _HA_ATOMIC_ADD(&s->be_tgcounters->res_out, bytes);
908
909
0
    if (s->sv_tgcounters)
910
0
      _HA_ATOMIC_ADD(&s->sv_tgcounters->res_out, bytes);
911
912
0
    if (sess->li_tgcounters)
913
0
      _HA_ATOMIC_ADD(&sess->li_tgcounters->res_out, bytes);
914
0
  }
915
0
}
916
917
/* Abort processing on the both channels in same time */
918
void stream_abort(struct stream *s)
919
0
{
920
0
  channel_abort(&s->req);
921
0
  channel_abort(&s->res);
922
0
}
923
924
/*
925
 * Returns a message to the client ; the connection is shut down for read,
926
 * and the request is cleared so that no server connection can be initiated.
927
 * The buffer is marked for read shutdown on the other side to protect the
928
 * message, and the buffer write is enabled. The message is contained in a
929
 * "chunk". If it is null, then an empty message is used. The reply buffer does
930
 * not need to be empty before this, and its contents will not be overwritten.
931
 * The primary goal of this function is to return error messages to a client.
932
 */
933
void stream_retnclose(struct stream *s, const struct buffer *msg)
934
0
{
935
0
  struct channel *ic = &s->req;
936
0
  struct channel *oc = &s->res;
937
938
0
  channel_auto_read(ic);
939
0
  channel_abort(ic);
940
0
  channel_erase(ic);
941
0
  channel_truncate(oc);
942
943
0
  if (likely(msg && msg->data))
944
0
    co_inject(oc, msg->area, msg->data);
945
946
0
  channel_auto_read(oc);
947
0
  channel_auto_close(oc);
948
0
  sc_schedule_abort(s->scb);
949
0
}
950
951
int stream_set_timeout(struct stream *s, enum act_timeout_name name, int timeout)
952
0
{
953
0
  switch (name) {
954
0
  case ACT_TIMEOUT_CLIENT:
955
0
    s->scf->ioto = timeout;
956
0
    return 1;
957
958
0
  case ACT_TIMEOUT_CONNECT:
959
0
    s->connect_timeout = timeout;
960
0
    return 1;
961
962
0
  case ACT_TIMEOUT_QUEUE:
963
0
    s->queue_timeout = timeout;
964
0
    return 1;
965
966
0
  case ACT_TIMEOUT_SERVER:
967
0
    s->scb->ioto = timeout;
968
0
    return 1;
969
970
0
  case ACT_TIMEOUT_TARPIT:
971
0
    s->tarpit_timeout = timeout;
972
0
    return 1;
973
974
0
  case ACT_TIMEOUT_TUNNEL:
975
0
    s->tunnel_timeout = timeout;
976
0
    return 1;
977
978
0
  default:
979
0
    return 0;
980
0
  }
981
0
}
982
983
/*
984
 * This function handles the transition between the SC_ST_CON state and the
985
 * SC_ST_EST state. It must only be called after switching from SC_ST_CON (or
986
 * SC_ST_INI or SC_ST_RDY) to SC_ST_EST, but only when a ->proto is defined.
987
 * Note that it will switch the interface to SC_ST_DIS if we already have
988
 * the SC_FL_ABRT_DONE flag, it means we were able to forward the request, and
989
 * receive the response, before process_stream() had the opportunity to
990
 * make the switch from SC_ST_CON to SC_ST_EST. When that happens, we want
991
 * to go through back_establish() anyway, to make sure the analysers run.
992
 * Timeouts are cleared. Error are reported on the channel so that analysers
993
 * can handle them.
994
 */
995
void back_establish(struct stream *s)
996
0
{
997
0
  struct connection *conn = sc_conn(s->scb);
998
0
  struct channel *req = &s->req;
999
0
  struct channel *rep = &s->res;
1000
0
  uint8_t do_log = 0;
1001
1002
0
  DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);
1003
  /* First, centralize the timers information, and clear any irrelevant
1004
   * timeout.
1005
   */
1006
0
  s->logs.t_connect = ns_to_ms(now_ns - s->logs.accept_ts);
1007
0
  s->conn_exp = TICK_ETERNITY;
1008
0
  s->flags &= ~SF_CONN_EXP;
1009
1010
  /* errors faced after sending data need to be reported */
1011
0
  if ((s->scb->flags & SC_FL_ERROR) && req->flags & CF_WROTE_DATA) {
1012
0
    s->req.flags |= CF_WRITE_EVENT;
1013
0
    s->res.flags |= CF_READ_EVENT;
1014
0
    s->conn_err_type = STRM_ET_DATA_ERR;
1015
0
    DBG_TRACE_STATE("read/write error", STRM_EV_STRM_PROC|STRM_EV_CS_ST|STRM_EV_STRM_ERR, s);
1016
0
  }
1017
1018
0
  if (objt_server(s->target))
1019
0
    health_adjust(__objt_server(s->target), HANA_STATUS_L4_OK);
1020
1021
0
  if (strm_fe(s)->to_log == LW_LOGSTEPS) {
1022
0
    if (log_orig_proxy(LOG_ORIG_TXN_CONNECT, strm_fe(s)))
1023
0
      do_log = 1;
1024
0
  }
1025
1026
0
  if (!IS_HTX_STRM(s)) { /* let's allow immediate data connection in this case */
1027
    /* if the user wants to log as soon as possible, without counting
1028
     * bytes from the server, then this is the right moment. */
1029
0
    if (strm_fe(s)->to_log != LW_LOGSTEPS &&
1030
0
        !lf_expr_isempty(&strm_fe(s)->logformat) && !(s->logs.logwait & LW_BYTES))
1031
0
      do_log = 1;
1032
0
  }
1033
0
  else {
1034
0
    s->scb->flags |= SC_FL_RCV_ONCE; /* a single read is enough to get response headers */
1035
0
  }
1036
1037
0
  if (do_log) {
1038
    /* note: no pend_pos here, session is established */
1039
0
    s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
1040
0
    s->do_log(s, log_orig(LOG_ORIG_TXN_CONNECT, LOG_ORIG_FL_NONE));
1041
0
  }
1042
1043
0
  rep->analysers |= strm_fe(s)->fe_rsp_ana | s->be->be_rsp_ana;
1044
1045
0
  se_have_more_data(s->scb->sedesc);
1046
0
  rep->flags |= CF_READ_EVENT; /* producer is now attached */
1047
0
  sc_ep_report_read_activity(s->scb);
1048
0
  if (conn) {
1049
    /* real connections have timeouts
1050
     * if already defined, it means that a set-timeout rule has
1051
     * been executed so do not overwrite them
1052
     */
1053
0
    if (!tick_isset(s->scb->ioto))
1054
0
      s->scb->ioto = s->be->timeout.server;
1055
0
    if (!tick_isset(s->tunnel_timeout))
1056
0
      s->tunnel_timeout = s->be->timeout.tunnel;
1057
1058
    /* The connection is now established, try to read data from the
1059
     * underlying layer, and subscribe to recv events. We use a
1060
     * delayed recv here to give a chance to the data to flow back
1061
     * by the time we process other tasks.
1062
     */
1063
0
    sc_chk_rcv(s->scb);
1064
0
  }
1065
  /* If we managed to get the whole response, and we don't have anything
1066
   * left to send, or can't, switch to SC_ST_DIS now. */
1067
0
  if ((s->scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) || (s->scf->flags & SC_FL_SHUT_DONE)) {
1068
0
    s->scb->state = SC_ST_DIS;
1069
0
    DBG_TRACE_STATE("response channel shutdwn for read/write", STRM_EV_STRM_PROC|STRM_EV_CS_ST|STRM_EV_STRM_ERR, s);
1070
0
  }
1071
1072
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);
1073
0
}
1074
1075
/* Set correct stream termination flags in case no analyser has done it. It
1076
 * also counts a failed request if the server state has not reached the request
1077
 * stage.
1078
 */
1079
void sess_set_term_flags(struct stream *s)
1080
0
{
1081
0
  if (!(s->flags & SF_FINST_MASK)) {
1082
0
    if (s->scb->state == SC_ST_INI) {
1083
      /* anything before REQ in fact */
1084
0
      if (s->sess->fe_tgcounters)
1085
0
        _HA_ATOMIC_INC(&s->sess->fe_tgcounters->failed_req);
1086
0
      if (s->sess->li_tgcounters)
1087
0
        _HA_ATOMIC_INC(&s->sess->li_tgcounters->failed_req);
1088
1089
0
      s->flags |= SF_FINST_R;
1090
0
    }
1091
0
    else if (s->scb->state == SC_ST_QUE)
1092
0
      s->flags |= SF_FINST_Q;
1093
0
    else if (sc_state_in(s->scb->state, SC_SB_REQ|SC_SB_TAR|SC_SB_ASS|SC_SB_CON|SC_SB_CER|SC_SB_RDY))
1094
0
      s->flags |= SF_FINST_C;
1095
0
    else if (s->scb->state == SC_ST_EST || s->prev_conn_state == SC_ST_EST)
1096
0
      s->flags |= SF_FINST_D;
1097
0
    else
1098
0
      s->flags |= SF_FINST_L;
1099
0
  }
1100
0
}
1101
1102
/* This function parses the use-service action ruleset. It executes
1103
 * the associated ACL and set an applet as a stream or txn final node.
1104
 * it returns ACT_RET_ERR if an error occurs, the proxy left in
1105
 * consistent state. It returns ACT_RET_STOP in success case because
1106
 * use-service must be a terminal action. Returns ACT_RET_YIELD
1107
 * if the initialisation function require more data.
1108
 */
1109
enum act_return process_use_service(struct act_rule *rule, struct proxy *px,
1110
                                    struct session *sess, struct stream *s, int flags)
1111
1112
0
{
1113
0
  struct appctx *appctx;
1114
1115
  /* Initialises the applet if it is required. */
1116
0
  if (flags & ACT_OPT_FIRST) {
1117
    /* Register applet. this function schedules the applet. */
1118
0
    s->target = &rule->applet.obj_type;
1119
0
    appctx = sc_applet_create(s->scb, objt_applet(s->target));
1120
0
    if (unlikely(!appctx))
1121
0
      return ACT_RET_ERR;
1122
1123
    /* Finish initialisation of the context. */
1124
0
    if (appctx_init(appctx) == -1)
1125
0
      return ACT_RET_ERR;
1126
0
  }
1127
0
  else
1128
0
    appctx = __sc_appctx(s->scb);
1129
1130
0
  if (rule->from != ACT_F_HTTP_REQ) {
1131
    /* report it if the request was intercepted by the frontend */
1132
0
    if (sess->fe == s->be && sess->fe_tgcounters)
1133
0
      _HA_ATOMIC_INC(&sess->fe_tgcounters->intercepted_req);
1134
1135
    /* The flag SF_ASSIGNED prevent from server assignment. */
1136
0
    s->flags |= SF_ASSIGNED;
1137
0
  }
1138
1139
  /* Now we can schedule the applet. */
1140
0
  applet_need_more_data(appctx);
1141
0
  appctx_wakeup(appctx);
1142
0
  return ACT_RET_STOP;
1143
0
}
1144
1145
/* Parses persist-rules attached to <fe> frontend and report the first matching
1146
 * entry, using <sess> session and <s> stream as sample source.
1147
 *
1148
 * As this function is called several times in the same stream context,
1149
 * <persist> will act as a caching value to avoid reprocessing of a similar
1150
 * ruleset. It must be set to a negative value for the first invocation.
1151
 *
1152
 * Returns 1 if a rule matches, else 0.
1153
 */
1154
static int lookup_fe_persist_rules(struct proxy *fe, struct session *sess,
1155
                                   struct stream *s, int *persist)
1156
0
{
1157
0
  struct persist_rule *prst_rule;
1158
1159
0
  if (*persist >= 0) {
1160
    /* Rules already processed, use previous computed result. */
1161
0
    return *persist;
1162
0
  }
1163
1164
0
  list_for_each_entry(prst_rule, &fe->persist_rules, list) {
1165
0
    if (!acl_match_cond(prst_rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
1166
0
      continue;
1167
1168
    /* force/ignore-persist match */
1169
0
    if (prst_rule->type == PERSIST_TYPE_BE_SWITCH) {
1170
0
      *persist = 1;
1171
0
      break;
1172
0
    }
1173
0
  }
1174
1175
0
  if (*persist < 0)
1176
0
    *persist = 0;
1177
0
  return *persist;
1178
0
}
1179
1180
/* This stream analyser checks the switching rules and changes the backend
1181
 * if appropriate. The default_backend rule is also considered, then the
1182
 * target backend's forced persistence rules are also evaluated last if any.
1183
 * It returns 1 if the processing can continue on next analysers, or zero if it
1184
 * either needs more data or wants to immediately abort the request.
1185
 */
1186
static int process_switching_rules(struct stream *s, struct channel *req, int an_bit)
1187
0
{
1188
0
  struct switching_rule *rule;
1189
0
  struct persist_rule *prst_rule;
1190
0
  struct session *sess = s->sess;
1191
0
  struct proxy *fe = sess->fe;
1192
0
  struct proxy *backend = NULL;
1193
0
  int fe_persist = -1;
1194
1195
0
  req->analysers &= ~an_bit;
1196
0
  req->analyse_exp = TICK_ETERNITY;
1197
1198
0
  DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
1199
1200
  /* now check whether we have some switching rules for this request */
1201
0
  if (!(s->flags & SF_BE_ASSIGNED)) {
1202
0
    list_for_each_entry(rule, &fe->switching_rules, list) {
1203
0
      if (!acl_match_cond(rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
1204
0
        continue;
1205
1206
0
      if (rule->dynamic) {
1207
0
        struct buffer *tmp;
1208
1209
0
        tmp = alloc_trash_chunk();
1210
0
        if (!tmp)
1211
0
          goto sw_failed;
1212
1213
0
        if (build_logline(s, tmp->area, tmp->size, &rule->be.expr))
1214
0
          backend = proxy_be_by_name(tmp->area);
1215
1216
0
        free_trash_chunk(tmp);
1217
0
        tmp = NULL;
1218
0
      }
1219
0
      else {
1220
0
        backend = rule->be.backend;
1221
0
      }
1222
1223
      /* If backend is ineligible, continue rules processing. */
1224
0
      if (backend && !be_is_eligible(backend) &&
1225
0
          !lookup_fe_persist_rules(fe, sess, s, &fe_persist)) {
1226
0
        backend = NULL;
1227
0
        continue;
1228
0
      }
1229
1230
      /* Break the loop at the first matching rule found. If
1231
       * the dynamic name resolution has fail, fallback will
1232
       * be performed on the default backend.
1233
       */
1234
0
      break;
1235
0
    }
1236
1237
    /* To ensure correct connection accounting on the backend, we
1238
     * have to assign one if it was not set. Default backend may be
1239
     * used if set, else it will stay on the current proxy. Also,
1240
     * don't do anything if an upgrade is already in progress.
1241
     */
1242
0
    if (!backend) {
1243
0
      if ((s->flags & SF_IGNORE)) {
1244
        /* TCP stream upgrade to HTTP/2. */
1245
0
        DBG_TRACE_DEVEL("leaving with no backend because of a destructive upgrade", STRM_EV_STRM_ANA, s);
1246
0
        return 0;
1247
0
      }
1248
1249
      /* Use default backend if possible or stay on the current proxy. */
1250
0
      if (fe->defbe.be &&
1251
0
          (be_is_eligible(fe->defbe.be) ||
1252
0
           lookup_fe_persist_rules(fe, sess, s, &fe_persist))) {
1253
0
        backend = fe->defbe.be;
1254
0
      }
1255
0
      else {
1256
0
        backend = s->be;
1257
0
      }
1258
0
    }
1259
1260
0
    if (!stream_set_backend(s, backend))
1261
0
      goto sw_failed;
1262
0
  }
1263
1264
0
  if (fe == s->be) {
1265
    /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1266
0
    s->req.analysers &= ~AN_REQ_INSPECT_BE;
1267
0
    s->req.analysers &= ~AN_REQ_HTTP_PROCESS_BE;
1268
0
    s->req.analysers &= ~AN_REQ_FLT_START_BE;
1269
0
  }
1270
0
  else {
1271
    /* Set the max connection retries for the stream. may be overwritten later */
1272
0
    s->max_retries = s->be->conn_retries;
1273
0
    s->scb->ioto = TICK_ETERNITY;
1274
0
    s->connect_timeout = TICK_ETERNITY;
1275
0
    s->queue_timeout = TICK_ETERNITY;
1276
0
    s->tunnel_timeout = TICK_ETERNITY;
1277
0
  }
1278
1279
1280
  /* Set the queue and connect timeouts if not set. May be overwritten later if backend has changed */
1281
0
  if (!tick_isset(s->connect_timeout))
1282
0
    s->connect_timeout = s->be->timeout.connect;
1283
0
  if (!tick_isset(s->queue_timeout))
1284
0
    s->queue_timeout = s->be->timeout.queue;
1285
1286
  /* as soon as we know the backend, we must check if we have a matching forced or ignored
1287
   * persistence rule, and report that in the stream.
1288
   */
1289
0
  list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
1290
0
    if (!acl_match_cond(prst_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
1291
0
      continue;
1292
1293
    /* no rule, or the rule matches */
1294
0
    if (prst_rule->type == PERSIST_TYPE_FORCE) {
1295
0
      s->flags |= SF_FORCE_PRST;
1296
0
    } else {
1297
0
      s->flags |= SF_IGNORE_PRST;
1298
0
    }
1299
0
    break;
1300
0
  }
1301
1302
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
1303
0
  return 1;
1304
1305
0
 sw_failed:
1306
  /* immediately abort this request in case of allocation failure */
1307
0
  stream_abort(s);
1308
1309
0
  if (!(s->flags & SF_ERR_MASK))
1310
0
    s->flags |= SF_ERR_RESOURCE;
1311
0
  if (!(s->flags & SF_FINST_MASK))
1312
0
    s->flags |= SF_FINST_R;
1313
1314
0
  if ((s->flags & SF_TXN_MASK) == SF_TXN_HTTP)
1315
0
    s->txn.http->status = 500;
1316
0
  s->req.analysers &= AN_REQ_FLT_END;
1317
0
  s->req.analyse_exp = TICK_ETERNITY;
1318
0
  DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_ANA|STRM_EV_STRM_ERR, s);
1319
0
  return 0;
1320
0
}
1321
1322
/* This stream analyser works on a request. It applies all use-server rules on
1323
 * it then returns 1. The data must already be present in the buffer otherwise
1324
 * they won't match. It always returns 1.
1325
 */
1326
static int process_server_rules(struct stream *s, struct channel *req, int an_bit)
1327
0
{
1328
0
  struct proxy *px = s->be;
1329
0
  struct session *sess = s->sess;
1330
0
  struct server_rule *rule;
1331
1332
0
  DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
1333
1334
0
  if (!(s->flags & SF_ASSIGNED)) {
1335
0
    list_for_each_entry(rule, &px->server_rules, list) {
1336
0
      struct server *srv;
1337
1338
0
      if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
1339
0
        continue;
1340
1341
0
      if (rule->dynamic) {
1342
0
        struct buffer *tmp = get_trash_chunk();
1343
1344
0
        if (!build_logline(s, tmp->area, tmp->size, &rule->expr))
1345
0
          break;
1346
1347
0
        srv = server_find_by_name(s->be, tmp->area);
1348
0
        if (!srv)
1349
0
          break;
1350
0
      }
1351
0
      else
1352
0
        srv = rule->srv.ptr;
1353
1354
0
      if ((srv->cur_state != SRV_ST_STOPPED) ||
1355
0
          (px->options & PR_O_PERSIST) ||
1356
0
          (s->flags & SF_FORCE_PRST)) {
1357
0
        s->flags |= SF_DIRECT | SF_ASSIGNED;
1358
0
        stream_set_srv_target(s, srv);
1359
0
        break;
1360
0
      }
1361
      /* if the server is not UP, let's go on with next rules
1362
       * just in case another one is suited.
1363
       */
1364
0
    }
1365
0
  }
1366
1367
0
  req->analysers &= ~an_bit;
1368
0
  req->analyse_exp = TICK_ETERNITY;
1369
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
1370
0
  return 1;
1371
0
}
1372
1373
static inline void sticking_rule_find_target(struct stream *s,
1374
                                             struct stktable *t, struct stksess *ts)
1375
0
{
1376
0
  struct proxy *px = s->be;
1377
0
  struct dict_entry *de;
1378
0
  void *ptr;
1379
0
  struct server *srv = NULL;
1380
0
  int id;
1381
1382
  /* Look for the server name previously stored in <t> stick-table */
1383
0
  HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
1384
0
  ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
1385
0
  de = stktable_data_cast(ptr, std_t_dict);
1386
0
  HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
1387
1388
0
  if (de) {
1389
0
    if (t->server_key_type == STKTABLE_SRV_NAME)
1390
0
      srv = server_find_by_name(px, de->value.key);
1391
0
    else if (t->server_key_type == STKTABLE_SRV_ADDR)
1392
0
      srv = server_find_by_addr(px, de->value.key);
1393
1394
0
    if (srv)
1395
0
      goto found;
1396
0
  }
1397
1398
  /* Look for the server ID */
1399
0
  HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
1400
0
  ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID);
1401
0
  id = stktable_data_cast(ptr, std_t_sint);
1402
0
  HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
1403
1404
0
  srv = server_find_by_id(px, id);
1405
0
  if (!srv)
1406
0
    return;
1407
1408
0
 found:
1409
0
  if ((srv->cur_state != SRV_ST_STOPPED) ||
1410
0
      (px->options & PR_O_PERSIST) || (s->flags & SF_FORCE_PRST)) {
1411
0
    s->flags |= SF_DIRECT | SF_ASSIGNED;
1412
0
    stream_set_srv_target(s, srv);
1413
0
  }
1414
0
}
1415
1416
/* This stream analyser works on a request. It applies all sticking rules on
1417
 * it then returns 1. The data must already be present in the buffer otherwise
1418
 * they won't match. It always returns 1.
1419
 */
1420
static int process_sticking_rules(struct stream *s, struct channel *req, int an_bit)
1421
0
{
1422
0
  struct proxy    *px   = s->be;
1423
0
  struct session *sess  = s->sess;
1424
0
  struct sticking_rule  *rule;
1425
1426
0
  DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
1427
1428
0
  list_for_each_entry(rule, &px->sticking_rules, list) {
1429
0
    struct stktable_key *key;
1430
0
    int i;
1431
1432
    /* Only the first stick store-request of each table is applied
1433
     * and other ones are ignored. The purpose is to allow complex
1434
     * configurations which look for multiple entries by decreasing
1435
     * order of precision and to stop at the first which matches.
1436
     * An example could be a store of the IP address from an HTTP
1437
     * header first, then from the source if not found.
1438
     */
1439
0
    if (rule->flags & STK_IS_STORE) {
1440
0
      for (i = 0; i < s->store_count; i++) {
1441
0
        if (rule->table.t == s->store[i].table)
1442
0
          break;
1443
0
      }
1444
1445
0
      if (i !=  s->store_count)
1446
0
        continue;
1447
0
    }
1448
1449
0
    if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
1450
0
      continue;
1451
1452
0
    key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL);
1453
0
    if (!key)
1454
0
      continue;
1455
1456
0
    if (rule->flags & STK_IS_MATCH) {
1457
0
      struct stksess *ts;
1458
1459
0
      if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
1460
0
        if (!(s->flags & SF_ASSIGNED))
1461
0
          sticking_rule_find_target(s, rule->table.t, ts);
1462
0
        stktable_touch_local(rule->table.t, ts, 1);
1463
0
      }
1464
0
    }
1465
0
    if (rule->flags & STK_IS_STORE) {
1466
0
      if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1467
0
        struct stksess *ts;
1468
1469
0
        ts = stksess_new(rule->table.t, key);
1470
0
        if (ts) {
1471
0
          s->store[s->store_count].table = rule->table.t;
1472
0
          s->store[s->store_count++].ts = ts;
1473
0
        }
1474
0
      }
1475
0
    }
1476
0
  }
1477
1478
0
  req->analysers &= ~an_bit;
1479
0
  req->analyse_exp = TICK_ETERNITY;
1480
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
1481
0
  return 1;
1482
0
}
1483
1484
/* This stream analyser works on a response. It applies all store rules on it
1485
 * then returns 1. The data must already be present in the buffer otherwise
1486
 * they won't match. It always returns 1.
1487
 */
1488
static int process_store_rules(struct stream *s, struct channel *rep, int an_bit)
1489
0
{
1490
0
  struct proxy    *px   = s->be;
1491
0
  struct session *sess  = s->sess;
1492
0
  struct sticking_rule  *rule;
1493
0
  int i;
1494
0
  int nbreq = s->store_count;
1495
1496
0
  DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
1497
1498
0
  list_for_each_entry(rule, &px->storersp_rules, list) {
1499
0
    struct stktable_key *key;
1500
1501
    /* Only the first stick store-response of each table is applied
1502
     * and other ones are ignored. The purpose is to allow complex
1503
     * configurations which look for multiple entries by decreasing
1504
     * order of precision and to stop at the first which matches.
1505
     * An example could be a store of a set-cookie value, with a
1506
     * fallback to a parameter found in a 302 redirect.
1507
     *
1508
     * The store-response rules are not allowed to override the
1509
     * store-request rules for the same table, but they may coexist.
1510
     * Thus we can have up to one store-request entry and one store-
1511
     * response entry for the same table at any time.
1512
     */
1513
0
    for (i = nbreq; i < s->store_count; i++) {
1514
0
      if (rule->table.t == s->store[i].table)
1515
0
        break;
1516
0
    }
1517
1518
    /* skip existing entries for this table */
1519
0
    if (i < s->store_count)
1520
0
      continue;
1521
1522
0
    if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL))
1523
0
      continue;
1524
1525
0
    key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL);
1526
0
    if (!key)
1527
0
      continue;
1528
1529
0
    if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1530
0
      struct stksess *ts;
1531
1532
0
      ts = stksess_new(rule->table.t, key);
1533
0
      if (ts) {
1534
0
        s->store[s->store_count].table = rule->table.t;
1535
0
        s->store[s->store_count++].ts = ts;
1536
0
      }
1537
0
    }
1538
0
  }
1539
1540
  /* process store request and store response */
1541
0
  for (i = 0; i < s->store_count; i++) {
1542
0
    struct stksess *ts;
1543
0
    void *ptr;
1544
0
    char *key;
1545
0
    struct dict_entry *de;
1546
0
    struct stktable *t = s->store[i].table;
1547
1548
0
    if (!objt_server(s->target) || (__objt_server(s->target)->flags & SRV_F_NON_STICK)) {
1549
0
      stksess_free(s->store[i].table, s->store[i].ts);
1550
0
      s->store[i].ts = NULL;
1551
0
      continue;
1552
0
    }
1553
1554
0
    ts = stktable_set_entry(t, s->store[i].ts);
1555
0
    if (ts != s->store[i].ts) {
1556
      /* the entry already existed, we can free ours */
1557
0
      stksess_free(t, s->store[i].ts);
1558
0
    }
1559
0
    s->store[i].ts = NULL;
1560
1561
0
    if (t->server_key_type == STKTABLE_SRV_NAME)
1562
0
      key = __objt_server(s->target)->id;
1563
0
    else if (t->server_key_type == STKTABLE_SRV_ADDR)
1564
0
      key = __objt_server(s->target)->addr_key;
1565
0
    else
1566
0
      key = NULL;
1567
1568
0
    HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
1569
0
    ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID);
1570
0
    stktable_data_cast(ptr, std_t_sint) = __objt_server(s->target)->puid;
1571
1572
0
    if (key) {
1573
0
      de = dict_insert(&server_key_dict, key);
1574
0
      if (de) {
1575
0
        ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
1576
0
        stktable_data_cast(ptr, std_t_dict) = de;
1577
0
      }
1578
0
    }
1579
1580
0
    HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
1581
1582
0
    stktable_touch_local(t, ts, 1);
1583
0
  }
1584
0
  s->store_count = 0; /* everything is stored */
1585
1586
0
  rep->analysers &= ~an_bit;
1587
0
  rep->analyse_exp = TICK_ETERNITY;
1588
1589
0
  DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
1590
0
  return 1;
1591
0
}
1592
1593
/* Set the stream to HTTP mode, if necessary. The minimal request HTTP analysers
1594
 * are set and the client mux is upgraded. It returns 1 if the stream processing
1595
 * may continue or 0 if it should be stopped. It happens on error or if the
1596
 * upgrade required a new stream. The mux protocol may be specified.
1597
 */
1598
int stream_set_http_mode(struct stream *s, const struct mux_proto_list *mux_proto)
1599
0
{
1600
0
  struct stconn *sc = s->scf;
1601
0
  struct connection  *conn;
1602
1603
  /* Already an HTTP stream */
1604
0
  if (IS_HTX_STRM(s))
1605
0
    return 1;
1606
1607
0
  s->req.analysers |= AN_REQ_WAIT_HTTP|AN_REQ_HTTP_PROCESS_FE;
1608
1609
0
  if (unlikely((s->flags & SF_TXN_MASK) != SF_TXN_HTTP && !http_create_txn(s)))
1610
0
    return 0;
1611
1612
0
  conn = sc_conn(sc);
1613
1614
0
  if (!sc_conn_ready(sc))
1615
0
    return 0;
1616
1617
0
  if (conn) {
1618
0
    se_have_more_data(s->scf->sedesc);
1619
    /* Make sure we're unsubscribed, the the new
1620
     * mux will probably want to subscribe to
1621
     * the underlying XPRT
1622
     */
1623
0
    if (s->scf->wait_event.events)
1624
0
      conn->mux->unsubscribe(sc, s->scf->wait_event.events, &(s->scf->wait_event));
1625
1626
0
    if (conn->mux->flags & MX_FL_NO_UPG)
1627
0
      return 0;
1628
1629
0
    sc_conn_prepare_endp_upgrade(sc);
1630
0
    if (conn_upgrade_mux_fe(conn, sc, &s->req.buf,
1631
0
          (mux_proto ? mux_proto->mux_proto : ist("")),
1632
0
          PROTO_MODE_HTTP)  == -1) {
1633
0
      sc_conn_abort_endp_upgrade(sc);
1634
0
      return 0;
1635
0
    }
1636
0
    sc_conn_commit_endp_upgrade(sc);
1637
1638
0
    s->req.flags &= ~(CF_READ_EVENT|CF_AUTO_CONNECT);
1639
0
    s->flags |= SF_IGNORE;
1640
0
    if (sc_ep_test(sc, SE_FL_DETACHED)) {
1641
      /* If stream connector is detached, it means it was not
1642
       * reused by the new mux. Son destroy it, disable
1643
       * logging, and abort the stream process. Thus the
1644
       * stream will be silently destroyed. The new mux will
1645
       * create new streams.
1646
       */
1647
0
      s->logs.logwait = 0;
1648
0
      s->logs.level = 0;
1649
0
      stream_abort(s);
1650
0
      s->req.analysers &= AN_REQ_FLT_END;
1651
0
      s->req.analyse_exp = TICK_ETERNITY;
1652
0
    }
1653
0
  }
1654
1655
0
  return 1;
1656
0
}
1657
1658
1659
/* Updates at once the channel flags, and timers of both stream connectors of a
1660
 * same stream, to complete the work after the analysers, then updates the data
1661
 * layer below. This will ensure that any synchronous update performed at the
1662
 * data layer will be reflected in the channel flags and/or stream connector.
1663
 * Note that this does not change the stream connector's current state, though
1664
 * it updates the previous state to the current one.
1665
 */
1666
void stream_update_both_sc(struct stream *s)
1667
0
{
1668
0
  struct stconn *scf = s->scf;
1669
0
  struct stconn *scb = s->scb;
1670
0
  struct channel *req = &s->req;
1671
0
  struct channel *res = &s->res;
1672
1673
0
  req->flags &= ~(CF_READ_EVENT|CF_WRITE_EVENT);
1674
0
  res->flags &= ~(CF_READ_EVENT|CF_WRITE_EVENT);
1675
1676
0
  s->prev_conn_state = scb->state;
1677
1678
  /* let's recompute both sides states */
1679
0
  if (sc_state_in(scf->state, SC_SB_RDY|SC_SB_EST))
1680
0
    sc_update(scf);
1681
1682
0
  if (sc_state_in(scb->state, SC_SB_RDY|SC_SB_EST))
1683
0
    sc_update(scb);
1684
1685
  /* stream connectors are processed outside of process_stream() and must be
1686
   * handled at the latest moment.
1687
   */
1688
0
  if (sc_appctx(scf)) {
1689
0
    if (sc_is_recv_allowed(scf) || sc_is_send_allowed(scf))
1690
0
      appctx_wakeup(__sc_appctx(scf));
1691
0
  }
1692
0
  if (sc_appctx(scb)) {
1693
0
    if (sc_is_recv_allowed(scb) || sc_is_send_allowed(scb))
1694
0
      appctx_wakeup(__sc_appctx(scb));
1695
0
  }
1696
0
}
1697
1698
/* check SC and channel timeouts, and close the corresponding stream connectors
1699
 * for future reads or writes.
1700
 * Note: this will also concern upper layers but we do not touch any other
1701
 * flag. We must be careful and correctly detect state changes when calling
1702
 * them.
1703
 */
1704
static void stream_handle_timeouts(struct stream *s)
1705
0
{
1706
0
  stream_check_conn_timeout(s);
1707
1708
0
  sc_check_timeouts(s->scf);
1709
0
  channel_check_timeout(&s->req);
1710
0
  sc_check_timeouts(s->scb);
1711
0
  channel_check_timeout(&s->res);
1712
1713
0
  if (unlikely(!(s->scb->flags & SC_FL_SHUT_DONE) && (s->req.flags & CF_WRITE_TIMEOUT))) {
1714
0
    stream_report_term_evt(s->scb, strm_tevt_type_tout);
1715
0
    s->scb->flags |= SC_FL_NOLINGER;
1716
0
    sc_shutdown(s->scb);
1717
0
  }
1718
1719
0
  if (unlikely(!(s->scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && (s->req.flags & CF_READ_TIMEOUT))) {
1720
0
    stream_report_term_evt(s->scf, strm_tevt_type_tout);
1721
0
    if (s->scf->flags & SC_FL_NOHALF)
1722
0
      s->scf->flags |= SC_FL_NOLINGER;
1723
0
    sc_abort(s->scf);
1724
0
  }
1725
0
  if (unlikely(!(s->scf->flags & SC_FL_SHUT_DONE) && (s->res.flags & CF_WRITE_TIMEOUT))) {
1726
0
    stream_report_term_evt(s->scf, strm_tevt_type_tout);
1727
0
    s->scf->flags |= SC_FL_NOLINGER;
1728
0
    sc_shutdown(s->scf);
1729
0
  }
1730
1731
0
  if (unlikely(!(s->scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && (s->res.flags & CF_READ_TIMEOUT))) {
1732
0
    stream_report_term_evt(s->scb, strm_tevt_type_tout);
1733
0
    if (s->scb->flags & SC_FL_NOHALF)
1734
0
      s->scb->flags |= SC_FL_NOLINGER;
1735
0
    sc_abort(s->scb);
1736
0
  }
1737
1738
0
  if (HAS_FILTERS(s))
1739
0
    flt_stream_check_timeouts(s);
1740
0
}
1741
1742
/* if the current task's wake_date was set, it's being profiled, thus we may
1743
 * report latencies and CPU usages in logs, so it's desirable to update the
1744
 * latency when entering process_stream().
1745
 */
1746
static void stream_cond_update_cpu_latency(struct stream *s)
1747
0
{
1748
0
  uint32_t lat;
1749
1750
0
  if (likely(!th_ctx->sched_wake_date))
1751
0
    return;
1752
1753
0
  lat = th_ctx->sched_call_date - th_ctx->sched_wake_date;
1754
0
  s->lat_time += lat;
1755
0
}
1756
1757
/* if the current task's wake_date was set, it's being profiled, thus we may
1758
 * report latencies and CPU usages in logs, so it's desirable to do that before
1759
 * logging in order to report accurate CPU usage. In this case we count that
1760
 * final part and reset the wake date so that the scheduler doesn't do it a
1761
 * second time, and by doing so we also avoid an extra call to clock_gettime().
1762
 * The CPU usage will be off by the little time needed to run over stream_free()
1763
 * but that's only marginal.
1764
 */
1765
static void stream_cond_update_cpu_usage(struct stream *s)
1766
0
{
1767
0
  uint32_t cpu;
1768
1769
  /* stats are only registered for non-zero wake dates */
1770
0
  if (likely(!th_ctx->sched_wake_date))
1771
0
    return;
1772
1773
0
  cpu = now_mono_time() - th_ctx->sched_call_date;
1774
0
  s->cpu_time += cpu;
1775
0
  HA_ATOMIC_ADD(&th_ctx->sched_profile_entry->cpu_time, cpu);
1776
0
  th_ctx->sched_wake_date = 0;
1777
0
}
1778
1779
/* this functions is called directly by the scheduler for tasks whose
1780
 * ->process points to process_stream(), and is used to keep latencies
1781
 * and CPU usage measurements accurate.
1782
 */
1783
void stream_update_timings(struct task *t, uint64_t lat, uint64_t cpu)
1784
0
{
1785
0
  struct stream *s = t->context;
1786
0
  s->lat_time += lat;
1787
0
  s->cpu_time += cpu;
1788
0
}
1789
1790
1791
/* This macro is very specific to the function below. See the comments in
1792
 * process_stream() below to understand the logic and the tests.
1793
 */
1794
0
#define UPDATE_ANALYSERS(real, list, back, flag) {     \
1795
0
    list = (((list) & ~(flag)) | ~(back)) & (real);   \
1796
0
    back = real;            \
1797
0
    if (!(list))           \
1798
0
      break;           \
1799
0
    if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1800
0
      continue;         \
1801
0
}
1802
1803
/* These 2 following macros call an analayzer for the specified channel if the
1804
 * right flag is set. The first one is used for "filterable" analyzers. If a
1805
 * stream has some registered filters, pre and post analyaze callbacks are
1806
 * called. The second are used for other analyzers (AN_REQ/RES_FLT_* and
1807
 * AN_REQ/RES_HTTP_XFER_BODY) */
1808
#define FLT_ANALYZE(strm, chn, fun, list, back, flag, ...)      \
1809
0
  {                 \
1810
0
    if ((list) & (flag)) {           \
1811
0
      if (HAS_FILTERS(strm)) {             \
1812
0
        if (!flt_pre_analyze((strm), (chn), (flag)))    \
1813
0
          break;               \
1814
0
        if (!fun((strm), (chn), (flag), ##__VA_ARGS__)) \
1815
0
          break;         \
1816
0
        if (!flt_post_analyze((strm), (chn), (flag))) \
1817
0
          break;         \
1818
0
      }             \
1819
0
      else {             \
1820
0
        if (!fun((strm), (chn), (flag), ##__VA_ARGS__)) \
1821
0
          break;         \
1822
0
      }             \
1823
0
      UPDATE_ANALYSERS((chn)->analysers, (list),    \
1824
0
           (back), (flag));     \
1825
0
    }                \
1826
0
  }
1827
1828
#define ANALYZE(strm, chn, fun, list, back, flag, ...)      \
1829
0
  {               \
1830
0
    if ((list) & (flag)) {         \
1831
0
      if (!fun((strm), (chn), (flag), ##__VA_ARGS__)) \
1832
0
        break;         \
1833
0
      UPDATE_ANALYSERS((chn)->analysers, (list),  \
1834
0
           (back), (flag));   \
1835
0
    }              \
1836
0
  }
1837
1838
/* Processes the client, server, request and response jobs of a stream task,
1839
 * then puts it back to the wait queue in a clean state, or cleans up its
1840
 * resources if it must be deleted. Returns in <next> the date the task wants
1841
 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1842
 * nothing too many times, the request and response buffers flags are monitored
1843
 * and each function is called only if at least another function has changed at
1844
 * least one flag it is interested in.
1845
 *
1846
 * TASK_WOKEN_* wake up reasons are mapped to STRM_EVT_*
1847
 *
1848
 * This task handler understands a few wake up events:
1849
 *  - STRM_EVT_MSG forces analysers to be re-evaluated
1850
 *  - STRM_EVT_TIMER forces timers to be re-evaluated
1851
 *  - STRM_EVT_SHUT_SRV_DOWN shuts the stream down on server down
1852
 *  - STRM_EVT_KILLED shuts the stream down on active kill
1853
 *  - STRM_EVT_SHUT_SRV_UP shuts the stream down because a preferred backend became available
1854
 */
1855
struct task *process_stream(struct task *t, void *context, unsigned int state)
1856
0
{
1857
0
  struct server *srv;
1858
0
  struct stream *s = context;
1859
0
  struct session *sess = s->sess;
1860
0
  unsigned int scf_flags, scb_flags;
1861
0
  unsigned int rqf_last, rpf_last;
1862
0
  unsigned int rq_prod_last, rq_cons_last;
1863
0
  unsigned int rp_cons_last, rp_prod_last;
1864
0
  unsigned int req_ana_back, res_ana_back;
1865
0
  struct channel *req, *res;
1866
0
  struct stconn *scf, *scb;
1867
0
  unsigned int rate;
1868
0
  unsigned int scf_send_cnt, scb_send_cnt;
1869
1870
0
  activity[tid].stream_calls++;
1871
0
  stream_cond_update_cpu_latency(s);
1872
1873
0
  req = &s->req;
1874
0
  res = &s->res;
1875
1876
0
  scf = s->scf;
1877
0
  scb = s->scb;
1878
1879
0
  DBG_TRACE_ENTER(STRM_EV_STRM_PROC, s);
1880
1881
  /* This flag must explicitly be set every time */
1882
0
  req->flags &= ~CF_WAKE_WRITE;
1883
0
  res->flags &= ~CF_WAKE_WRITE;
1884
1885
  /* Keep a copy of req/rep flags so that we can detect shutdowns */
1886
0
  rqf_last = req->flags & ~CF_MASK_ANALYSER;
1887
0
  rpf_last = res->flags & ~CF_MASK_ANALYSER;
1888
1889
  /* we don't want the stream connector functions to recursively wake us up */
1890
0
  scf->flags |= SC_FL_DONT_WAKE;
1891
0
  scb->flags |= SC_FL_DONT_WAKE;
1892
1893
  /* Keep a copy of SC flags */
1894
0
  scf_flags = scf->flags;
1895
0
  scb_flags = scb->flags;
1896
0
  scf_send_cnt = scb_send_cnt = 0;
1897
1898
  /* update pending events */
1899
0
  s->pending_events |= stream_map_task_state(state);
1900
0
  s->pending_events |= HA_ATOMIC_XCHG(&s->new_events, STRM_EVT_NONE);
1901
1902
0
  if (s->pending_events & (STRM_EVT_SHUT_SRV_DOWN|STRM_EVT_SHUT_SRV_UP|STRM_EVT_KILLED)) {
1903
    /* that an instant kill message, the reason is in _UEVT* */
1904
0
    stream_shutdown_self(s, ((s->pending_events & STRM_EVT_SHUT_SRV_DOWN) ? SF_ERR_DOWN :
1905
0
           (s->pending_events & STRM_EVT_SHUT_SRV_UP) ? SF_ERR_UP:
1906
0
           SF_ERR_KILLED));
1907
0
  }
1908
1909
  /* we're starting to work with this endpoint, let's flag it */
1910
0
  if (unlikely(!sc_ep_test(scf, SE_FL_APP_STARTED)))
1911
0
    sc_ep_set(scf, SE_FL_APP_STARTED);
1912
1913
  /* First, attempt to receive pending data from I/O layers */
1914
0
  sc_sync_recv(scf);
1915
0
  sc_sync_recv(scb);
1916
1917
  /* Let's check if we're looping without making any progress, e.g. due
1918
   * to a bogus analyser or the fact that we're ignoring a read0. The
1919
   * call_rate counter only counts calls with no progress made.
1920
   */
1921
0
  if (!((req->flags | res->flags) & (CF_READ_EVENT|CF_WRITE_EVENT))) {
1922
0
    rate = update_freq_ctr(&s->call_rate, 1);
1923
0
    if (rate >= 100000 && s->call_rate.prev_ctr) // make sure to wait at least a full second
1924
0
      stream_dump_and_crash(&s->obj_type, read_freq_ctr(&s->call_rate));
1925
0
  }
1926
1927
  /* this data may be no longer valid, clear it */
1928
0
  if ((s->flags & SF_TXN_MASK) == SF_TXN_HTTP)
1929
0
    memset(&s->txn.http->auth, 0, sizeof(s->txn.http->auth));
1930
1931
  /* 1a: Check for low level timeouts if needed. We just set a flag on
1932
   * stream connectors when their timeouts have expired.
1933
   */
1934
0
  if (unlikely(s->pending_events & STRM_EVT_TIMER)) {
1935
0
    stream_handle_timeouts(s);
1936
1937
    /* Once in a while we're woken up because the task expires. But
1938
     * this does not necessarily mean that a timeout has been
1939
     * reached.  So let's not run a whole stream processing if only
1940
     * an expiration timeout needs to be refreshed. To do so, we
1941
     * must be sure only the TIMER event was triggered and not
1942
     * error/timeout/abort/shut occurred. on both sides.
1943
     */
1944
0
    if (!((scf->flags | scb->flags) & (SC_FL_ERROR|SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_SHUT_DONE)) &&
1945
0
        !((req->flags | res->flags) & (CF_READ_EVENT|CF_READ_TIMEOUT|CF_WRITE_EVENT|CF_WRITE_TIMEOUT)) &&
1946
0
        !(s->flags & SF_CONN_EXP) &&
1947
0
        (s->pending_events  == STRM_EVT_TIMER)) {
1948
0
      scf->flags &= ~SC_FL_DONT_WAKE;
1949
0
      scb->flags &= ~SC_FL_DONT_WAKE;
1950
0
      goto update_exp_and_leave;
1951
0
    }
1952
0
  }
1953
1954
0
 resync_stconns:
1955
0
  if (!stream_alloc_work_buffer(s)) {
1956
0
    scf->flags &= ~SC_FL_DONT_WAKE;
1957
0
    scb->flags &= ~SC_FL_DONT_WAKE;
1958
    /* we're stuck for now */
1959
0
    t->expire = TICK_ETERNITY;
1960
0
    goto leave;
1961
0
  }
1962
1963
  /* 1b: check for low-level errors reported at the stream connector.
1964
   * First we check if it's a retryable error (in which case we don't
1965
   * want to tell the buffer). Otherwise we report the error one level
1966
   * upper by setting flags into the buffers. Note that the side towards
1967
   * the client cannot have connect (hence retryable) errors. Also, the
1968
   * connection setup code must be able to deal with any type of abort.
1969
   */
1970
0
  s->passes_stconn++;
1971
0
  srv = objt_server(s->target);
1972
0
  if (unlikely(scf->flags & SC_FL_ERROR)) {
1973
0
    if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS)) {
1974
0
      sc_abort(scf);
1975
0
      sc_shutdown(scf);
1976
0
      if (!(req->analysers) && !(res->analysers)) {
1977
0
        COUNT_IF(1, "Report a client abort (no analysers)");
1978
0
        if (s->be_tgcounters)
1979
0
          _HA_ATOMIC_INC(&s->be_tgcounters->cli_aborts);
1980
0
        if (sess->fe_tgcounters)
1981
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->cli_aborts);
1982
0
        if (sess->li_tgcounters)
1983
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->cli_aborts);
1984
0
        if (s->sv_tgcounters)
1985
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->cli_aborts);
1986
0
        if (!(s->flags & SF_ERR_MASK))
1987
0
          s->flags |= SF_ERR_CLICL;
1988
0
        if (!(s->flags & SF_FINST_MASK))
1989
0
          s->flags |= SF_FINST_D;
1990
0
      }
1991
0
    }
1992
0
  }
1993
1994
0
  if (unlikely(scb->flags & SC_FL_ERROR)) {
1995
0
    if (sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS)) {
1996
0
      sc_abort(scb);
1997
0
      sc_shutdown(scb);
1998
0
      if (s->be_tgcounters)
1999
0
        _HA_ATOMIC_INC(&s->be_tgcounters->failed_resp);
2000
0
      if (s->sv_tgcounters)
2001
0
        _HA_ATOMIC_INC(&s->sv_tgcounters->failed_resp);
2002
0
      if (!(req->analysers) && !(res->analysers)) {
2003
0
        COUNT_IF(1, "Report a client abort (no analysers)");
2004
0
        if (s->be_tgcounters)
2005
0
          _HA_ATOMIC_INC(&s->be_tgcounters->srv_aborts);
2006
0
        if (sess->fe_tgcounters)
2007
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->srv_aborts);
2008
0
        if (sess->li_tgcounters)
2009
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->srv_aborts);
2010
0
        if (s->sv_tgcounters)
2011
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->srv_aborts);
2012
0
        if (!(s->flags & SF_ERR_MASK))
2013
0
          s->flags |= SF_ERR_SRVCL;
2014
0
        if (!(s->flags & SF_FINST_MASK))
2015
0
          s->flags |= SF_FINST_D;
2016
0
      }
2017
0
    }
2018
    /* note: maybe we should process connection errors here ? */
2019
0
  }
2020
2021
0
  if (sc_state_in(scb->state, SC_SB_CON|SC_SB_RDY)) {
2022
    /* we were trying to establish a connection on the server side,
2023
     * maybe it succeeded, maybe it failed, maybe we timed out, ...
2024
     */
2025
0
    if (scb->state == SC_ST_RDY)
2026
0
      back_handle_st_rdy(s);
2027
0
    else if (s->scb->state == SC_ST_CON)
2028
0
      back_handle_st_con(s);
2029
2030
0
    if (scb->state == SC_ST_CER)
2031
0
      back_handle_st_cer(s);
2032
0
    else if (scb->state == SC_ST_EST)
2033
0
      back_establish(s);
2034
2035
    /* state is now one of SC_ST_CON (still in progress), SC_ST_EST
2036
     * (established), SC_ST_DIS (abort), SC_ST_CLO (last error),
2037
     * SC_ST_ASS/SC_ST_TAR/SC_ST_REQ for retryable errors.
2038
     */
2039
0
  }
2040
2041
0
  rq_prod_last = scf->state;
2042
0
  rq_cons_last = scb->state;
2043
0
  rp_cons_last = scf->state;
2044
0
  rp_prod_last = scb->state;
2045
2046
  /* Check for connection closure */
2047
0
  DBG_TRACE_POINT(STRM_EV_STRM_PROC, s);
2048
2049
  /* nothing special to be done on client side */
2050
0
  if (unlikely(scf->state == SC_ST_DIS)) {
2051
0
    scf->state = SC_ST_CLO;
2052
2053
    /* This is needed only when debugging is enabled, to indicate
2054
     * client-side close.
2055
     */
2056
0
    if (unlikely((global.mode & MODE_DEBUG) &&
2057
0
           (!(global.mode & MODE_QUIET) ||
2058
0
            (global.mode & MODE_VERBOSE)))) {
2059
0
      chunk_printf(&trash, "%08x:%s.clicls[%04x:%04x]\n",
2060
0
             s->uniq_id, s->be->id,
2061
0
             (unsigned short)conn_fd(sc_conn(scf)),
2062
0
             (unsigned short)conn_fd(sc_conn(scb)));
2063
0
      DISGUISE(write(1, trash.area, trash.data));
2064
0
    }
2065
0
  }
2066
2067
  /* When a server-side connection is released, we have to count it and
2068
   * check for pending connections on this server.
2069
   */
2070
0
  if (unlikely(scb->state == SC_ST_DIS)) {
2071
0
    scb->state = SC_ST_CLO;
2072
0
    srv = objt_server(s->target);
2073
0
    if (srv) {
2074
0
      if (s->flags & SF_CURR_SESS) {
2075
0
        s->flags &= ~SF_CURR_SESS;
2076
0
        _HA_ATOMIC_DEC(&srv->cur_sess);
2077
0
      }
2078
      /*
2079
       * We don't want to release the slot just yet
2080
       * if we're using strict-maxconn, we want to
2081
       * free the connection before.
2082
       */
2083
0
      if (!(srv->flags & SRV_F_STRICT_MAXCONN)) {
2084
0
        sess_change_server(s, NULL);
2085
0
        if (may_dequeue_tasks(srv, s->be))
2086
0
          process_srv_queue(srv);
2087
0
      }
2088
0
    }
2089
2090
    /* This is needed only when debugging is enabled, to indicate
2091
     * server-side close.
2092
     */
2093
0
    if (unlikely((global.mode & MODE_DEBUG) &&
2094
0
           (!(global.mode & MODE_QUIET) ||
2095
0
            (global.mode & MODE_VERBOSE)))) {
2096
0
      if (s->prev_conn_state == SC_ST_EST) {
2097
0
        chunk_printf(&trash, "%08x:%s.srvcls[%04x:%04x]\n",
2098
0
               s->uniq_id, s->be->id,
2099
0
               (unsigned short)conn_fd(sc_conn(scf)),
2100
0
               (unsigned short)conn_fd(sc_conn(scb)));
2101
0
        DISGUISE(write(1, trash.area, trash.data));
2102
0
      }
2103
0
    }
2104
0
  }
2105
2106
  /*
2107
   * Note: of the transient states (REQ, CER, DIS), only REQ may remain
2108
   * at this point.
2109
   */
2110
2111
0
 resync_request:
2112
0
  s->passes_reqana++;
2113
  /* Analyse request */
2114
0
  if (((req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
2115
0
      ((scf->flags ^ scf_flags) & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) ||
2116
0
      ((scb->flags ^ scb_flags) & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) ||
2117
0
      (req->analysers && (scb->flags & SC_FL_SHUT_DONE)) ||
2118
0
      scf->state != rq_prod_last ||
2119
0
      scb->state != rq_cons_last ||
2120
0
      s->pending_events & STRM_EVT_MSG) {
2121
0
    unsigned int scf_flags_ana = scf->flags;
2122
0
    unsigned int scb_flags_ana = scb->flags;
2123
2124
0
    if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) {
2125
0
      int max_loops = global.tune.maxpollevents;
2126
0
      unsigned int ana_list;
2127
0
      unsigned int ana_back;
2128
2129
      /* it's up to the analysers to stop new connections,
2130
       * disable reading or closing. Note: if an analyser
2131
       * disables any of these bits, it is responsible for
2132
       * enabling them again when it disables itself, so
2133
       * that other analysers are called in similar conditions.
2134
       */
2135
0
      channel_auto_read(req);
2136
0
      channel_auto_connect(req);
2137
0
      channel_auto_close(req);
2138
2139
      /* We will call all analysers for which a bit is set in
2140
       * req->analysers, following the bit order from LSB
2141
       * to MSB. The analysers must remove themselves from
2142
       * the list when not needed. Any analyser may return 0
2143
       * to break out of the loop, either because of missing
2144
       * data to take a decision, or because it decides to
2145
       * kill the stream. We loop at least once through each
2146
       * analyser, and we may loop again if other analysers
2147
       * are added in the middle.
2148
       *
2149
       * We build a list of analysers to run. We evaluate all
2150
       * of these analysers in the order of the lower bit to
2151
       * the higher bit. This ordering is very important.
2152
       * An analyser will often add/remove other analysers,
2153
       * including itself. Any changes to itself have no effect
2154
       * on the loop. If it removes any other analysers, we
2155
       * want those analysers not to be called anymore during
2156
       * this loop. If it adds an analyser that is located
2157
       * after itself, we want it to be scheduled for being
2158
       * processed during the loop. If it adds an analyser
2159
       * which is located before it, we want it to switch to
2160
       * it immediately, even if it has already been called
2161
       * once but removed since.
2162
       *
2163
       * In order to achieve this, we compare the analyser
2164
       * list after the call with a copy of it before the
2165
       * call. The work list is fed with analyser bits that
2166
       * appeared during the call. Then we compare previous
2167
       * work list with the new one, and check the bits that
2168
       * appeared. If the lowest of these bits is lower than
2169
       * the current bit, it means we have enabled a previous
2170
       * analyser and must immediately loop again.
2171
       */
2172
2173
0
      ana_list = ana_back = req->analysers;
2174
0
      s->rules_bcount = 0;
2175
0
      while (ana_list && max_loops--) {
2176
        /* Warning! ensure that analysers are always placed in ascending order! */
2177
0
        ANALYZE    (s, req, flt_start_analyze,          ana_list, ana_back, AN_REQ_FLT_START_FE);
2178
0
        FLT_ANALYZE(s, req, tcp_inspect_request,        ana_list, ana_back, AN_REQ_INSPECT_FE);
2179
0
        FLT_ANALYZE(s, req, http_wait_for_request,      ana_list, ana_back, AN_REQ_WAIT_HTTP);
2180
0
        FLT_ANALYZE(s, req, http_wait_for_request_body, ana_list, ana_back, AN_REQ_HTTP_BODY);
2181
0
        FLT_ANALYZE(s, req, http_process_req_common,    ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE, sess->fe);
2182
0
        FLT_ANALYZE(s, req, process_switching_rules,    ana_list, ana_back, AN_REQ_SWITCHING_RULES);
2183
0
        ANALYZE    (s, req, flt_start_analyze,          ana_list, ana_back, AN_REQ_FLT_START_BE);
2184
0
        FLT_ANALYZE(s, req, tcp_inspect_request,        ana_list, ana_back, AN_REQ_INSPECT_BE);
2185
0
        FLT_ANALYZE(s, req, http_process_req_common,    ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE, s->be);
2186
0
        FLT_ANALYZE(s, req, http_process_tarpit,        ana_list, ana_back, AN_REQ_HTTP_TARPIT);
2187
0
        FLT_ANALYZE(s, req, process_server_rules,       ana_list, ana_back, AN_REQ_SRV_RULES);
2188
0
        FLT_ANALYZE(s, req, http_process_request,       ana_list, ana_back, AN_REQ_HTTP_INNER);
2189
0
        FLT_ANALYZE(s, req, tcp_persist_rdp_cookie,     ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
2190
0
        FLT_ANALYZE(s, req, process_sticking_rules,     ana_list, ana_back, AN_REQ_STICKING_RULES);
2191
0
        ANALYZE    (s, req, flt_analyze_http_headers,   ana_list, ana_back, AN_REQ_FLT_HTTP_HDRS);
2192
0
        ANALYZE    (s, req, http_request_forward_body,  ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
2193
0
        ANALYZE    (s, req, pcli_wait_for_request,      ana_list, ana_back, AN_REQ_WAIT_CLI);
2194
0
        ANALYZE    (s, req, flt_xfer_data,              ana_list, ana_back, AN_REQ_FLT_XFER_DATA);
2195
0
        ANALYZE    (s, req, flt_end_analyze,            ana_list, ana_back, AN_REQ_FLT_END);
2196
0
        break;
2197
0
      }
2198
0
    }
2199
2200
0
    rq_prod_last = scf->state;
2201
0
    rq_cons_last = scb->state;
2202
0
    req->flags &= ~CF_WAKE_ONCE;
2203
0
    rqf_last = req->flags;
2204
0
    scf_flags = (scf_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED));
2205
0
    scb_flags = (scb_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED));
2206
2207
0
    if (((scf->flags ^ scf_flags_ana) & (SC_FL_EOS|SC_FL_ABRT_DONE)) || ((scb->flags ^ scb_flags_ana) & SC_FL_SHUT_DONE))
2208
0
      goto resync_request;
2209
0
  }
2210
2211
  /* we'll monitor the request analysers while parsing the response,
2212
   * because some response analysers may indirectly enable new request
2213
   * analysers (eg: HTTP keep-alive).
2214
   */
2215
0
  req_ana_back = req->analysers;
2216
2217
0
 resync_response:
2218
0
  s->passes_resana++;
2219
  /* Analyse response */
2220
2221
0
  if (((res->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
2222
0
      ((scb->flags ^ scb_flags) & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) ||
2223
0
      ((scf->flags ^ scf_flags) & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) ||
2224
0
      (res->analysers && (scf->flags & SC_FL_SHUT_DONE)) ||
2225
0
      scf->state != rp_cons_last ||
2226
0
      scb->state != rp_prod_last ||
2227
0
      s->pending_events & STRM_EVT_MSG) {
2228
0
    unsigned int scb_flags_ana = scb->flags;
2229
0
    unsigned int scf_flags_ana = scf->flags;
2230
2231
0
    if (sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) {
2232
0
      int max_loops = global.tune.maxpollevents;
2233
0
      unsigned int ana_list;
2234
0
      unsigned int ana_back;
2235
2236
      /* it's up to the analysers to stop disable reading or
2237
       * closing. Note: if an analyser disables any of these
2238
       * bits, it is responsible for enabling them again when
2239
       * it disables itself, so that other analysers are called
2240
       * in similar conditions.
2241
       */
2242
0
      channel_auto_read(res);
2243
0
      channel_auto_close(res);
2244
2245
      /* We will call all analysers for which a bit is set in
2246
       * res->analysers, following the bit order from LSB
2247
       * to MSB. The analysers must remove themselves from
2248
       * the list when not needed. Any analyser may return 0
2249
       * to break out of the loop, either because of missing
2250
       * data to take a decision, or because it decides to
2251
       * kill the stream. We loop at least once through each
2252
       * analyser, and we may loop again if other analysers
2253
       * are added in the middle.
2254
       */
2255
2256
0
      ana_list = ana_back = res->analysers;
2257
0
      s->rules_bcount = 0;
2258
0
      while (ana_list && max_loops--) {
2259
        /* Warning! ensure that analysers are always placed in ascending order! */
2260
0
        ANALYZE    (s, res, flt_start_analyze,          ana_list, ana_back, AN_RES_FLT_START_FE);
2261
0
        ANALYZE    (s, res, flt_start_analyze,          ana_list, ana_back, AN_RES_FLT_START_BE);
2262
0
        FLT_ANALYZE(s, res, tcp_inspect_response,       ana_list, ana_back, AN_RES_INSPECT);
2263
0
        FLT_ANALYZE(s, res, http_wait_for_response,     ana_list, ana_back, AN_RES_WAIT_HTTP);
2264
0
        FLT_ANALYZE(s, res, process_store_rules,        ana_list, ana_back, AN_RES_STORE_RULES);
2265
0
        FLT_ANALYZE(s, res, http_process_res_common,    ana_list, ana_back, AN_RES_HTTP_PROCESS_BE, s->be);
2266
0
        ANALYZE    (s, res, flt_analyze_http_headers,   ana_list, ana_back, AN_RES_FLT_HTTP_HDRS);
2267
0
        ANALYZE    (s, res, http_response_forward_body, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
2268
0
        ANALYZE    (s, res, pcli_wait_for_response,     ana_list, ana_back, AN_RES_WAIT_CLI);
2269
0
        ANALYZE    (s, res, flt_xfer_data,              ana_list, ana_back, AN_RES_FLT_XFER_DATA);
2270
0
        ANALYZE    (s, res, flt_end_analyze,            ana_list, ana_back, AN_RES_FLT_END);
2271
0
        break;
2272
0
      }
2273
0
    }
2274
2275
0
    rp_cons_last = scf->state;
2276
0
    rp_prod_last = scb->state;
2277
0
    res->flags &= ~CF_WAKE_ONCE;
2278
0
    rpf_last = res->flags;
2279
0
    scb_flags = (scb_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED));
2280
0
    scf_flags = (scf_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED));
2281
2282
0
    if (((scb->flags ^ scb_flags_ana) & (SC_FL_EOS|SC_FL_ABRT_DONE)) || ((scf->flags ^ scf_flags_ana) & SC_FL_SHUT_DONE))
2283
0
      goto resync_response;
2284
0
  }
2285
2286
  /* we'll monitor the response analysers because some response analysers
2287
   * may be enabled/disabled later
2288
   */
2289
0
  res_ana_back = res->analysers;
2290
2291
  /* maybe someone has added some request analysers, so we must check and loop */
2292
0
  if (req->analysers & ~req_ana_back)
2293
0
    goto resync_request;
2294
2295
0
  if ((req->flags & ~rqf_last) & CF_MASK_ANALYSER)
2296
0
    goto resync_request;
2297
2298
  /* FIXME: here we should call protocol handlers which rely on
2299
   * both buffers.
2300
   */
2301
2302
0
  s->passes_propag++;
2303
  /*
2304
   * Now we propagate unhandled errors to the stream. Normally
2305
   * we're just in a data phase here since it means we have not
2306
   * seen any analyser who could set an error status.
2307
   */
2308
0
  srv = objt_server(s->target);
2309
0
  if (unlikely(!(s->flags & SF_ERR_MASK))) {
2310
0
    if ((scf->flags & SC_FL_ERROR) || req->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
2311
      /* Report it if the client got an error or a read timeout expired */
2312
0
      req->analysers &= AN_REQ_FLT_END;
2313
0
      channel_auto_close(req);
2314
0
      if (scf->flags & SC_FL_ERROR) {
2315
0
        if (s->be_tgcounters)
2316
0
          _HA_ATOMIC_INC(&s->be_tgcounters->cli_aborts);
2317
0
        if (sess->fe_tgcounters)
2318
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->cli_aborts);
2319
0
        if (sess->li_tgcounters)
2320
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->cli_aborts);
2321
0
        if (s->sv_tgcounters)
2322
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->cli_aborts);
2323
0
        s->flags |= SF_ERR_CLICL;
2324
0
        COUNT_IF(1, "Report unhandled client error");
2325
0
      }
2326
0
      else if (req->flags & CF_READ_TIMEOUT) {
2327
0
        if (s->be_tgcounters)
2328
0
          _HA_ATOMIC_INC(&s->be_tgcounters->cli_aborts);
2329
0
        if (sess->fe_tgcounters)
2330
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->cli_aborts);
2331
0
        if (sess->li_tgcounters)
2332
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->cli_aborts);
2333
0
        if (s->sv_tgcounters)
2334
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->cli_aborts);
2335
0
        s->flags |= SF_ERR_CLITO;
2336
0
        COUNT_IF(1, "Report unhandled client timeout (RD)");
2337
0
      }
2338
0
      else {
2339
0
        if (s->be_tgcounters)
2340
0
          _HA_ATOMIC_INC(&s->be_tgcounters->srv_aborts);
2341
0
        if (sess->fe_tgcounters)
2342
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->srv_aborts);
2343
0
        if (sess->li_tgcounters)
2344
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->srv_aborts);
2345
0
        if (s->sv_tgcounters)
2346
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->srv_aborts);
2347
0
        s->flags |= SF_ERR_SRVTO;
2348
0
        COUNT_IF(1, "Report unhandled server timeout (WR)");
2349
0
      }
2350
0
      sess_set_term_flags(s);
2351
2352
      /* Abort the request if a client error occurred while
2353
       * the backend stream connector is in the SC_ST_INI
2354
       * state. It is switched into the SC_ST_CLO state and
2355
       * the request channel is erased. */
2356
0
      if (scb->state == SC_ST_INI) {
2357
0
        s->scb->state = SC_ST_CLO;
2358
0
        channel_abort(req);
2359
0
        if (IS_HTX_STRM(s))
2360
0
          channel_htx_erase(req, htxbuf(&req->buf));
2361
0
        else
2362
0
          channel_erase(req);
2363
0
      }
2364
0
    }
2365
0
    else if ((scb->flags & SC_FL_ERROR) || res->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
2366
      /* Report it if the server got an error or a read timeout expired */
2367
0
      res->analysers &= AN_RES_FLT_END;
2368
0
      channel_auto_close(res);
2369
0
      if (scb->flags & SC_FL_ERROR) {
2370
0
        if (s->be_tgcounters)
2371
0
          _HA_ATOMIC_INC(&s->be_tgcounters->srv_aborts);
2372
0
        if (sess->fe_tgcounters)
2373
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->srv_aborts);
2374
0
        if (sess->li_tgcounters)
2375
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->srv_aborts);
2376
0
        if (s->sv_tgcounters)
2377
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->srv_aborts);
2378
0
        s->flags |= SF_ERR_SRVCL;
2379
0
        COUNT_IF(1, "Report unhandled server error");
2380
0
      }
2381
0
      else if (res->flags & CF_READ_TIMEOUT) {
2382
0
        if (s->be_tgcounters)
2383
0
          _HA_ATOMIC_INC(&s->be_tgcounters->srv_aborts);
2384
0
        if (sess->fe_tgcounters)
2385
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->srv_aborts);
2386
0
        if (sess->li_tgcounters)
2387
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->srv_aborts);
2388
0
        if (s->sv_tgcounters)
2389
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->srv_aborts);
2390
0
        s->flags |= SF_ERR_SRVTO;
2391
0
        COUNT_IF(1, "Report unhandled server timeout (RD)");
2392
0
      }
2393
0
      else {
2394
0
        if (s->be_tgcounters)
2395
0
          _HA_ATOMIC_INC(&s->be_tgcounters->cli_aborts);
2396
0
        if (sess->fe_tgcounters)
2397
0
          _HA_ATOMIC_INC(&sess->fe_tgcounters->cli_aborts);
2398
0
        if (sess->li_tgcounters)
2399
0
          _HA_ATOMIC_INC(&sess->li_tgcounters->cli_aborts);
2400
0
        if (s->sv_tgcounters)
2401
0
          _HA_ATOMIC_INC(&s->sv_tgcounters->cli_aborts);
2402
0
        s->flags |= SF_ERR_CLITO;
2403
0
        COUNT_IF(1, "Report unhandled client timeout (WR)");
2404
0
      }
2405
0
      sess_set_term_flags(s);
2406
0
    }
2407
0
  }
2408
2409
  /*
2410
   * Here we take care of forwarding unhandled data. This also includes
2411
   * connection establishments and shutdown requests.
2412
   */
2413
2414
2415
  /* If no one is interested in analysing data, it's time to forward
2416
   * everything. We configure the buffer to forward indefinitely.
2417
   * Note that we're checking SC_FL_ABRT_WANTED as an indication of a possible
2418
   * recent call to channel_abort().
2419
   */
2420
0
  if (unlikely((!req->analysers || (req->analysers == AN_REQ_FLT_END && !(req->flags & CF_FLT_ANALYZE))) &&
2421
0
         !(scf->flags & SC_FL_ABRT_WANTED) && !(scb->flags & SC_FL_SHUT_DONE) &&
2422
0
         (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) &&
2423
0
         (req->to_forward != CHN_INFINITE_FORWARD))) {
2424
    /* This buffer is freewheeling, there's no analyser
2425
     * attached to it. If any data are left in, we'll permit them to
2426
     * move.
2427
     */
2428
0
    channel_auto_read(req);
2429
0
    channel_auto_connect(req);
2430
0
    channel_auto_close(req);
2431
2432
0
    if (IS_HTX_STRM(s)) {
2433
0
      struct htx *htx = htxbuf(&req->buf);
2434
2435
      /* We'll let data flow between the producer (if still connected)
2436
       * to the consumer.
2437
       */
2438
0
      co_set_data(req, htx->data);
2439
0
      if ((global.tune.options & GTUNE_USE_FAST_FWD) &&
2440
0
          !(scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && !(scb->flags & SC_FL_SHUT_WANTED))
2441
0
        channel_htx_forward_forever(req, htx);
2442
0
    }
2443
0
    else {
2444
      /* We'll let data flow between the producer (if still connected)
2445
       * to the consumer (which might possibly not be connected yet).
2446
       */
2447
0
      c_adv(req, ci_data(req));
2448
0
      if ((global.tune.options & GTUNE_USE_FAST_FWD) &&
2449
0
          !(scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && !(scb->flags & SC_FL_SHUT_WANTED))
2450
0
        channel_forward_forever(req);
2451
0
    }
2452
0
  }
2453
2454
  /* reflect what the L7 analysers have seen last */
2455
0
  rqf_last = req->flags;
2456
0
  scf_flags = (scf_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED));
2457
0
  scb_flags = (scb_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED));
2458
2459
  /* it's possible that an upper layer has requested a connection setup or abort.
2460
   * There are 2 situations where we decide to establish a new connection :
2461
   *  - there are data scheduled for emission in the buffer
2462
   *  - the CF_AUTO_CONNECT flag is set (active connection)
2463
   */
2464
0
  if (scb->state == SC_ST_INI) {
2465
0
    if (!(scb->flags & SC_FL_SHUT_DONE)) {
2466
0
      if ((req->flags & CF_AUTO_CONNECT) || co_data(req)) {
2467
        /* If we have an appctx, there is no connect method, so we
2468
         * immediately switch to the connected state, otherwise we
2469
         * perform a connection request.
2470
         */
2471
0
        scb->state = SC_ST_REQ; /* new connection requested */
2472
0
        s->conn_retries = 0;
2473
0
        if ((s->be->retry_type &~ PR_RE_CONN_FAILED) &&
2474
0
            (s->be->mode == PR_MODE_HTTP) &&
2475
0
            !(s->txn.http->flags & TX_D_L7_RETRY))
2476
0
          s->txn.http->flags |= TX_L7_RETRY;
2477
2478
0
        if (proxy_abrt_close(s->be)) {
2479
0
          struct connection *conn = sc_conn(scf);
2480
2481
0
          se_have_more_data(scf->sedesc);
2482
0
          if (conn && conn->mux && conn->mux->ctl)
2483
0
            conn->mux->ctl(conn, MUX_CTL_SUBS_RECV, NULL);
2484
0
        }
2485
0
      }
2486
0
    }
2487
0
    else {
2488
0
      s->scb->state = SC_ST_CLO; /* shutw+ini = abort */
2489
0
      sc_schedule_shutdown(scb);
2490
0
      sc_schedule_abort(scb);
2491
0
    }
2492
0
  }
2493
2494
2495
  /* we may have a pending connection request, or a connection waiting
2496
   * for completion.
2497
   */
2498
0
  if (sc_state_in(scb->state, SC_SB_REQ|SC_SB_QUE|SC_SB_TAR|SC_SB_ASS)) {
2499
    /* prune the request variables and swap to the response variables. */
2500
0
    if (s->vars_reqres.scope != SCOPE_RES) {
2501
0
      vars_prune(&s->vars_reqres, s->sess, s);
2502
0
      vars_init_head(&s->vars_reqres, SCOPE_RES);
2503
0
    }
2504
2505
0
    do {
2506
0
      s->passes_connect++;
2507
2508
      /* nb: step 1 might switch from QUE to ASS, but we first want
2509
       * to give a chance to step 2 to perform a redirect if needed.
2510
       */
2511
0
      if (scb->state != SC_ST_REQ)
2512
0
        back_try_conn_req(s);
2513
0
      if (scb->state == SC_ST_REQ)
2514
0
        back_handle_st_req(s);
2515
2516
      /* get a chance to complete an immediate connection setup */
2517
0
      if (scb->state == SC_ST_RDY)
2518
0
        goto resync_stconns;
2519
2520
      /* applets directly go to the ESTABLISHED state. Similarly,
2521
       * servers experience the same fate when their connection
2522
       * is reused.
2523
       */
2524
0
      if (unlikely(scb->state == SC_ST_EST))
2525
0
        back_establish(s);
2526
2527
0
      srv = objt_server(s->target);
2528
0
      if (scb->state == SC_ST_ASS && srv && srv->rdr_len && (s->flags & SF_REDIRECTABLE))
2529
0
        http_perform_server_redirect(s, scb);
2530
2531
0
      if (unlikely((s->be->options2 & PR_O2_USE_SBUF_QUEUE) && scb->state == SC_ST_QUE && !HAS_REQ_DATA_FILTERS(s))) {
2532
0
        struct buffer sbuf = BUF_NULL;
2533
2534
0
        if (IS_HTX_STRM(s)) {
2535
0
          if (!htx_move_to_small_buffer(&sbuf, &req->buf))
2536
0
            break;
2537
0
        }
2538
0
        else {
2539
0
          if (b_size(&req->buf) == global.tune.bufsize_small ||
2540
0
              b_data(&req->buf) > global.tune.bufsize_small)
2541
0
            break;
2542
0
          if (!b_alloc_small(&sbuf))
2543
0
            break;
2544
0
          b_xfer(&sbuf, &req->buf, b_data(&req->buf));
2545
0
        }
2546
2547
0
        b_free(&req->buf);
2548
0
        offer_buffers(s, 1);
2549
0
        req->buf = sbuf;
2550
0
        DBG_TRACE_DEVEL("request moved to a small buffer", STRM_EV_STRM_PROC, s);
2551
0
      }
2552
2553
0
    } while (scb->state == SC_ST_ASS);
2554
0
  }
2555
2556
  /* Let's see if we can send the pending request now */
2557
0
  sc_sync_send(scb, scb_send_cnt++);
2558
2559
  /*
2560
   * Now forward all shutdown requests between both sides of the request buffer
2561
   */
2562
2563
  /* first, let's check if the request buffer needs to shutdown(write), which may
2564
   * happen either because the input is closed or because we want to force a close
2565
   * once the server has begun to respond. If a half-closed timeout is set, we adjust
2566
   * the other side's timeout as well. However this doesn't have effect during the
2567
   * connection setup unless the backend has abortonclose set.
2568
   */
2569
0
  if (unlikely((req->flags & CF_AUTO_CLOSE) && (scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) &&
2570
0
         !(scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) &&
2571
0
         (scb->state != SC_ST_CON || proxy_abrt_close(s->be)))) {
2572
0
    sc_schedule_shutdown(scb);
2573
0
  }
2574
2575
  /* shutdown(write) pending */
2576
0
  if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
2577
0
         ((!co_data(req) && !sc_ep_have_ff_data(scb)) || (req->flags & CF_WRITE_TIMEOUT)))) {
2578
0
    if (scf->flags & SC_FL_ERROR)
2579
0
      scb->flags |= SC_FL_NOLINGER;
2580
0
    sc_shutdown(scb);
2581
0
  }
2582
2583
  /* shutdown(write) done on server side, we must stop the client too */
2584
0
  if (unlikely((scb->flags & SC_FL_SHUT_DONE) && !(scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED))) &&
2585
0
      !req->analysers)
2586
0
    sc_schedule_abort(scf);
2587
2588
  /* shutdown(read) pending */
2589
0
  if (unlikely((scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) == SC_FL_ABRT_WANTED)) {
2590
0
    if (scf->flags & SC_FL_NOHALF)
2591
0
      scf->flags |= SC_FL_NOLINGER;
2592
0
    sc_abort(scf);
2593
0
  }
2594
2595
  /* Benchmarks have shown that it's optimal to do a full resync now */
2596
0
  if (scf->state == SC_ST_DIS ||
2597
0
      sc_state_in(scb->state, SC_SB_RDY|SC_SB_DIS) ||
2598
0
      ((scf->flags & SC_FL_ERROR) && scf->state != SC_ST_CLO) ||
2599
0
      ((scb->flags & SC_FL_ERROR) && scb->state != SC_ST_CLO))
2600
0
    goto resync_stconns;
2601
2602
  /* otherwise we want to check if we need to resync the req buffer or not */
2603
0
  if (((scf->flags ^ scf_flags) & (SC_FL_EOS|SC_FL_ABRT_DONE)) || ((scb->flags ^ scb_flags) & SC_FL_SHUT_DONE))
2604
0
    goto resync_request;
2605
2606
  /* perform output updates to the response buffer */
2607
2608
  /* If no one is interested in analysing data, it's time to forward
2609
   * everything. We configure the buffer to forward indefinitely.
2610
   * Note that we're checking SC_FL_ABRT_WANTED as an indication of a possible
2611
   * recent call to channel_abort().
2612
   */
2613
0
  if (unlikely((!res->analysers || (res->analysers == AN_RES_FLT_END && !(res->flags & CF_FLT_ANALYZE))) &&
2614
0
         !(scf->flags & SC_FL_ABRT_WANTED) && !(scb->flags & SC_FL_SHUT_WANTED) &&
2615
0
         sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO) &&
2616
0
         (res->to_forward != CHN_INFINITE_FORWARD))) {
2617
    /* This buffer is freewheeling, there's no analyser
2618
     * attached to it. If any data are left in, we'll permit them to
2619
     * move.
2620
     */
2621
0
    channel_auto_read(res);
2622
0
    channel_auto_close(res);
2623
2624
0
    if (IS_HTX_STRM(s)) {
2625
0
      struct htx *htx = htxbuf(&res->buf);
2626
2627
      /* We'll let data flow between the producer (if still connected)
2628
       * to the consumer.
2629
       */
2630
0
      co_set_data(res, htx->data);
2631
0
      if ((global.tune.options & GTUNE_USE_FAST_FWD) &&
2632
0
          !(scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && !(scb->flags & SC_FL_SHUT_WANTED))
2633
0
        channel_htx_forward_forever(res, htx);
2634
0
    }
2635
0
    else {
2636
      /* We'll let data flow between the producer (if still connected)
2637
       * to the consumer.
2638
       */
2639
0
      c_adv(res, ci_data(res));
2640
0
      if ((global.tune.options & GTUNE_USE_FAST_FWD) &&
2641
0
          !(scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && !(scb->flags & SC_FL_SHUT_WANTED))
2642
0
        channel_forward_forever(res);
2643
0
    }
2644
2645
    /* if we have no analyser anymore in any direction and have a
2646
     * tunnel timeout set, use it now. Note that we must respect
2647
     * the half-closed timeouts as well.
2648
     */
2649
0
    if (!req->analysers && s->tunnel_timeout) {
2650
0
      scf->ioto = scb->ioto = s->tunnel_timeout;
2651
2652
0
      if (!IS_HTX_STRM(s)) {
2653
0
        if ((scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_SHUT_DONE)) && tick_isset(sess->fe->timeout.clientfin))
2654
0
          scf->ioto = sess->fe->timeout.clientfin;
2655
0
        if ((scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_SHUT_DONE)) && tick_isset(s->be->timeout.serverfin))
2656
0
          scb->ioto = s->be->timeout.serverfin;
2657
0
      }
2658
0
    }
2659
0
  }
2660
2661
  /* reflect what the L7 analysers have seen last */
2662
0
  rpf_last = res->flags;
2663
0
  scb_flags = (scb_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED));
2664
0
  scf_flags = (scf_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED));
2665
2666
  /* Let's see if we can send the pending response now */
2667
0
  sc_sync_send(scf, scf_send_cnt++);
2668
2669
  /*
2670
   * Now forward all shutdown requests between both sides of the buffer
2671
   */
2672
2673
  /*
2674
   * FIXME: this is probably where we should produce error responses.
2675
   */
2676
2677
  /* first, let's check if the response buffer needs to shutdown(write) */
2678
0
  if (unlikely((res->flags & CF_AUTO_CLOSE) && (scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) &&
2679
0
         !(scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)))) {
2680
0
    sc_schedule_shutdown(scf);
2681
0
  }
2682
2683
  /* shutdown(write) pending */
2684
0
  if (unlikely((scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
2685
0
         ((!co_data(res) && !sc_ep_have_ff_data(scf)) || (res->flags & CF_WRITE_TIMEOUT)))) {
2686
0
    sc_shutdown(scf);
2687
0
  }
2688
2689
  /* shutdown(write) done on the client side, we must stop the server too */
2690
0
  if (unlikely((scf->flags & SC_FL_SHUT_DONE) && !(scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED))) &&
2691
0
      !res->analysers)
2692
0
    sc_schedule_abort(scb);
2693
2694
  /* shutdown(read) pending */
2695
0
  if (unlikely((scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) == SC_FL_ABRT_WANTED)) {
2696
0
    if (scb->flags & SC_FL_NOHALF)
2697
0
      scb->flags |= SC_FL_NOLINGER;
2698
0
    sc_abort(scb);
2699
0
  }
2700
2701
0
  if (scf->state == SC_ST_DIS ||
2702
0
      sc_state_in(scb->state, SC_SB_RDY|SC_SB_DIS) ||
2703
0
      ((scf->flags & SC_FL_ERROR) && scf->state != SC_ST_CLO) ||
2704
0
      ((scb->flags & SC_FL_ERROR) && scb->state != SC_ST_CLO))
2705
0
    goto resync_stconns;
2706
2707
0
  if ((req->flags & ~rqf_last) & CF_MASK_ANALYSER)
2708
0
    goto resync_request;
2709
2710
0
  if (((scb->flags ^ scb_flags) & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) ||
2711
0
      ((scf->flags ^ scf_flags) & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) ||
2712
0
      (res->analysers ^ res_ana_back))
2713
0
    goto resync_response;
2714
2715
0
  if ((((req->flags ^ rqf_last) | (res->flags ^ rpf_last)) & CF_MASK_ANALYSER) ||
2716
0
      (req->analysers ^ req_ana_back))
2717
0
    goto resync_request;
2718
2719
  /* we're interested in getting wakeups again */
2720
0
  scf->flags &= ~SC_FL_DONT_WAKE;
2721
0
  scb->flags &= ~SC_FL_DONT_WAKE;
2722
2723
0
  if (likely((scf->state != SC_ST_CLO) || !sc_state_in(scb->state, SC_SB_INI|SC_SB_CLO) ||
2724
0
       (req->analysers & AN_REQ_FLT_END) || (res->analysers & AN_RES_FLT_END))) {
2725
0
    if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED) && !(s->flags & SF_IGNORE))
2726
0
      stream_process_counters(s);
2727
2728
0
    stream_update_both_sc(s);
2729
2730
    /* Reset pending events now */
2731
0
    s->pending_events = STRM_EVT_NONE;
2732
2733
0
  update_exp_and_leave:
2734
    /* Note: please ensure that if you branch here you disable SC_FL_DONT_WAKE */
2735
0
    if (!req->analysers)
2736
0
      req->analyse_exp = TICK_ETERNITY;
2737
0
    if (!res->analysers)
2738
0
      res->analyse_exp = TICK_ETERNITY;
2739
2740
0
    if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED) &&
2741
0
              (!tick_isset(req->analyse_exp) || tick_is_expired(req->analyse_exp, now_ms)))
2742
0
      req->analyse_exp = tick_add(now_ms, 5000);
2743
2744
0
    t->expire = (tick_is_expired(t->expire, now_ms) ? 0 : t->expire);
2745
0
    t->expire = tick_first(t->expire, sc_ep_rcv_ex(scf));
2746
0
    t->expire = tick_first(t->expire, sc_ep_snd_ex(scf));
2747
0
    t->expire = tick_first(t->expire, sc_ep_rcv_ex(scb));
2748
0
    t->expire = tick_first(t->expire, sc_ep_snd_ex(scb));
2749
0
    t->expire = tick_first(t->expire, req->analyse_exp);
2750
0
    t->expire = tick_first(t->expire, res->analyse_exp);
2751
0
    t->expire = tick_first(t->expire, s->conn_exp);
2752
2753
0
    if (unlikely(tick_is_expired(t->expire, now_ms))) {
2754
      /* Some events prevented the timeouts to be handled but nothing evolved.
2755
         So do it now and resyunc the stconns
2756
       */
2757
0
      stream_handle_timeouts(s);
2758
0
      goto resync_stconns;
2759
0
    }
2760
0
  leave:
2761
0
    s->pending_events &= ~STRM_EVT_TIMER;
2762
0
    stream_release_buffers(s);
2763
2764
0
    DBG_TRACE_DEVEL("queuing", STRM_EV_STRM_PROC, s);
2765
0
    return t; /* nothing more to do */
2766
0
  }
2767
2768
0
  DBG_TRACE_DEVEL("releasing", STRM_EV_STRM_PROC, s);
2769
2770
0
  if (s->flags & SF_BE_ASSIGNED)
2771
0
    _HA_ATOMIC_DEC(&s->be->beconn);
2772
2773
0
  if (unlikely((global.mode & MODE_DEBUG) &&
2774
0
         (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2775
0
    chunk_printf(&trash, "%08x:%s.closed[%04x:%04x]\n",
2776
0
           s->uniq_id, s->be->id,
2777
0
           (unsigned short)conn_fd(sc_conn(scf)),
2778
0
           (unsigned short)conn_fd(sc_conn(scb)));
2779
0
    DISGUISE(write(1, trash.area, trash.data));
2780
0
  }
2781
2782
0
  if (!(s->flags & SF_IGNORE)) {
2783
0
    uint8_t do_log = 0;
2784
2785
0
    s->logs.t_close = ns_to_ms(now_ns - s->logs.accept_ts);
2786
2787
0
    stream_process_counters(s);
2788
2789
0
    if ((s->flags & SF_TXN_MASK) == SF_TXN_HTTP && s->txn.http->status) {
2790
0
      int n;
2791
2792
0
      n = s->txn.http->status / 100;
2793
0
      if (n < 1 || n > 5)
2794
0
        n = 0;
2795
2796
0
      if (sess->fe->mode == PR_MODE_HTTP && sess->fe_tgcounters) {
2797
0
        _HA_ATOMIC_INC(&sess->fe_tgcounters->p.http.rsp[n]);
2798
0
      }
2799
0
      if ((s->flags & SF_BE_ASSIGNED) &&
2800
0
          (s->be->mode == PR_MODE_HTTP) &&
2801
0
          s->be_tgcounters) {
2802
0
        _HA_ATOMIC_INC(&s->be_tgcounters->p.http.rsp[n]);
2803
0
        _HA_ATOMIC_INC(&s->be_tgcounters->p.http.cum_req);
2804
0
      }
2805
0
    }
2806
2807
    /* let's do a final log if we need it */
2808
0
    if (sess->fe->to_log == LW_LOGSTEPS) {
2809
0
      if (log_orig_proxy(LOG_ORIG_TXN_CLOSE, sess->fe))
2810
0
        do_log = 1;
2811
0
    }
2812
0
    else if (!lf_expr_isempty(&sess->fe->logformat) && s->logs.logwait)
2813
0
      do_log = 1;
2814
2815
0
    if (do_log &&
2816
0
        !(s->flags & SF_MONITOR) &&
2817
0
        (!(sess->fe->options & PR_O_NULLNOLOG) || s->scf->bytes_in)) {
2818
      /* we may need to know the position in the queue */
2819
0
      pendconn_free(s);
2820
2821
0
      stream_cond_update_cpu_usage(s);
2822
0
      s->do_log(s, log_orig(LOG_ORIG_TXN_CLOSE, LOG_ORIG_FL_NONE));
2823
0
    }
2824
2825
    /* update time stats for this stream */
2826
0
    stream_update_time_stats(s);
2827
0
  }
2828
2829
  /* the task MUST not be in the run queue anymore */
2830
0
  stream_free(s);
2831
0
  task_destroy(t);
2832
0
  return NULL;
2833
0
}
2834
2835
/* Update the stream's backend and server time stats */
2836
void stream_update_time_stats(struct stream *s)
2837
0
{
2838
0
  int t_request;
2839
0
  int t_queue;
2840
0
  int t_connect;
2841
0
  int t_data;
2842
0
  int t_close;
2843
0
  struct server *srv;
2844
0
  unsigned int samples_window;
2845
2846
0
  t_request = 0;
2847
0
  t_queue   = s->logs.t_queue;
2848
0
  t_connect = s->logs.t_connect;
2849
0
  t_close   = s->logs.t_close;
2850
0
  t_data    = s->logs.t_data;
2851
2852
0
  if (s->be->mode != PR_MODE_HTTP)
2853
0
    t_data = t_connect;
2854
2855
0
  if (t_connect < 0 || t_data < 0)
2856
0
    return;
2857
2858
0
  if ((llong)(s->logs.request_ts - s->logs.accept_ts) >= 0)
2859
0
    t_request = ns_to_ms(s->logs.request_ts - s->logs.accept_ts);
2860
2861
0
  t_data    -= t_connect;
2862
0
  t_connect -= t_queue;
2863
0
  t_queue   -= t_request;
2864
2865
0
  srv = objt_server(s->target);
2866
0
  if (srv) {
2867
0
    if (s->sv_tgcounters)
2868
0
      samples_window = (((s->be->mode == PR_MODE_HTTP) ?
2869
0
        HA_ATOMIC_LOAD(&s->sv_tgcounters->p.http.cum_req) : HA_ATOMIC_LOAD(&s->sv_tgcounters->cum_lbconn)) > TIME_STATS_SAMPLES) ? TIME_STATS_SAMPLES : 0;
2870
0
    else
2871
0
      samples_window = 0;
2872
0
    swrate_add_dynamic(&srv->counters.q_time, samples_window, t_queue);
2873
0
    swrate_add_dynamic(&srv->counters.c_time, samples_window, t_connect);
2874
0
    swrate_add_dynamic(&srv->counters.d_time, samples_window, t_data);
2875
0
    swrate_add_dynamic(&srv->counters.t_time, samples_window, t_close);
2876
0
    COUNTERS_UPDATE_MAX(&srv->counters.qtime_max, t_queue);
2877
0
    COUNTERS_UPDATE_MAX(&srv->counters.ctime_max, t_connect);
2878
0
    COUNTERS_UPDATE_MAX(&srv->counters.dtime_max, t_data);
2879
0
    COUNTERS_UPDATE_MAX(&srv->counters.ttime_max, t_close);
2880
0
  }
2881
0
  if (s->be_tgcounters)
2882
0
    samples_window = (((s->be->mode == PR_MODE_HTTP) ?
2883
0
      HA_ATOMIC_LOAD(&s->be_tgcounters->p.http.cum_req) : HA_ATOMIC_LOAD(&s->be_tgcounters->cum_lbconn)) > TIME_STATS_SAMPLES) ? TIME_STATS_SAMPLES : 0;
2884
0
  else
2885
0
    samples_window = 0;
2886
0
  swrate_add_dynamic(&s->be->be_counters.q_time, samples_window, t_queue);
2887
0
  swrate_add_dynamic(&s->be->be_counters.c_time, samples_window, t_connect);
2888
0
  swrate_add_dynamic(&s->be->be_counters.d_time, samples_window, t_data);
2889
0
  swrate_add_dynamic(&s->be->be_counters.t_time, samples_window, t_close);
2890
0
  COUNTERS_UPDATE_MAX(&s->be->be_counters.qtime_max, t_queue);
2891
0
  COUNTERS_UPDATE_MAX(&s->be->be_counters.ctime_max, t_connect);
2892
0
  COUNTERS_UPDATE_MAX(&s->be->be_counters.dtime_max, t_data);
2893
0
  COUNTERS_UPDATE_MAX(&s->be->be_counters.ttime_max, t_close);
2894
0
}
2895
2896
/*
2897
 * This function adjusts sess->srv_conn and maintains the previous and new
2898
 * server's served stream counts. Setting newsrv to NULL is enough to release
2899
 * current connection slot. This function also notifies any LB algo which might
2900
 * expect to be informed about any change in the number of active streams on a
2901
 * server.
2902
 */
2903
void sess_change_server(struct stream *strm, struct server *newsrv)
2904
0
{
2905
0
  struct server *oldsrv = strm->srv_conn;
2906
2907
  /* Dynamic servers may be deleted during process lifetime. This
2908
   * operation is always conducted under thread isolation. Several
2909
   * conditions prevent deletion, one of them is if server streams list
2910
   * is not empty. sess_change_server() uses stream_add_srv_conn() to
2911
   * ensure the latter condition.
2912
   *
2913
   * A race condition could exist for stream which referenced a server
2914
   * instance (s->target) without registering itself in its server list.
2915
   * This is notably the case for SF_DIRECT streams which referenced a
2916
   * server earlier during process_stream(). However at this time the
2917
   * code is deemed safe as process_stream() cannot be rescheduled before
2918
   * invocation of sess_change_server().
2919
   */
2920
2921
0
  if (oldsrv == newsrv) {
2922
    /*
2923
     * It is assumed if the stream has a non-NULL srv_conn, then its
2924
     * served field has been incremented, so we have to decrement it now.
2925
     */
2926
0
    if (oldsrv)
2927
0
      _HA_ATOMIC_DEC(&oldsrv->served);
2928
0
    return;
2929
0
  }
2930
2931
0
  if (oldsrv) {
2932
    /* Note: we cannot decrement served after calling server_drop_conn
2933
     * because that one may rely on served (e.g. for leastconn). The
2934
     * real need here is to make sure that when served==0, no stream
2935
     * knows the server anymore, mainly for server removal purposes,
2936
     * and that removal will be done under isolation anyway. Thus by
2937
     * decrementing served after detaching from the list, we're
2938
     * guaranteeing that served==0 implies that no stream is in the
2939
     * list anymore, which is a sufficient guarantee for that goal.
2940
     */
2941
0
    _HA_ATOMIC_DEC(&oldsrv->proxy->served);
2942
0
    stream_del_srv_conn(strm);
2943
0
    _HA_ATOMIC_DEC(&oldsrv->served);
2944
0
    __ha_barrier_atomic_store();
2945
0
    if (oldsrv->proxy->lbprm.ops && oldsrv->proxy->lbprm.ops->server_drop_conn)
2946
0
      oldsrv->proxy->lbprm.ops->server_drop_conn(oldsrv);
2947
0
  }
2948
2949
0
  if (newsrv) {
2950
0
    _HA_ATOMIC_INC(&newsrv->proxy->served);
2951
0
    __ha_barrier_atomic_store();
2952
0
    if (newsrv->proxy->lbprm.ops && newsrv->proxy->lbprm.ops->server_take_conn)
2953
0
      newsrv->proxy->lbprm.ops->server_take_conn(newsrv);
2954
0
    stream_add_srv_conn(strm, newsrv);
2955
0
  }
2956
0
}
2957
2958
/* Handle server-side errors for default protocols. It is called whenever a a
2959
 * connection setup is aborted or a request is aborted in queue. It sets the
2960
 * stream termination flags so that the caller does not have to worry about
2961
 * them. It's installed as ->srv_error for the server-side stream connector.
2962
 */
2963
void default_srv_error(struct stream *s, struct stconn *sc)
2964
0
{
2965
0
  int err_type = s->conn_err_type;
2966
0
  int err = 0, fin = 0;
2967
2968
0
  if (err_type & STRM_ET_QUEUE_ABRT) {
2969
0
    err = SF_ERR_CLICL;
2970
0
    fin = SF_FINST_Q;
2971
0
  }
2972
0
  else if (err_type & STRM_ET_CONN_ABRT) {
2973
0
    err = SF_ERR_CLICL;
2974
0
    fin = SF_FINST_C;
2975
0
  }
2976
0
  else if (err_type & STRM_ET_QUEUE_TO) {
2977
0
    err = SF_ERR_SRVTO;
2978
0
    fin = SF_FINST_Q;
2979
0
  }
2980
0
  else if (err_type & STRM_ET_QUEUE_ERR) {
2981
0
    err = SF_ERR_SRVCL;
2982
0
    fin = SF_FINST_Q;
2983
0
  }
2984
0
  else if (err_type & STRM_ET_CONN_TO) {
2985
0
    err = SF_ERR_SRVTO;
2986
0
    fin = SF_FINST_C;
2987
0
  }
2988
0
  else if (err_type & STRM_ET_CONN_ERR) {
2989
0
    err = SF_ERR_SRVCL;
2990
0
    fin = SF_FINST_C;
2991
0
  }
2992
0
  else if (err_type & STRM_ET_CONN_RES) {
2993
0
    err = SF_ERR_RESOURCE;
2994
0
    fin = SF_FINST_C;
2995
0
  }
2996
0
  else /* STRM_ET_CONN_OTHER and others */ {
2997
0
    err = SF_ERR_INTERNAL;
2998
0
    fin = SF_FINST_C;
2999
0
  }
3000
3001
0
  if (!(s->flags & SF_ERR_MASK))
3002
0
    s->flags |= err;
3003
0
  if (!(s->flags & SF_FINST_MASK))
3004
0
    s->flags |= fin;
3005
0
}
3006
3007
/* shutdown the stream from itself. It's also possible for another one from the
3008
 * same thread but then an explicit wakeup will be needed since this function
3009
 * does not perform it. <why> is a set of SF_ERR_* flags to pass as the cause
3010
 * for shutting down.
3011
 */
3012
void stream_shutdown_self(struct stream *stream, int why)
3013
0
{
3014
0
  if (stream->scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
3015
0
    return;
3016
3017
0
  stream->task->nice = 1024;
3018
0
  if (!(stream->flags & SF_ERR_MASK))
3019
0
    stream->flags |= why;
3020
3021
0
  if (objt_server(stream->target)) {
3022
0
    if (stream->flags & SF_CURR_SESS) {
3023
0
      stream->flags &= ~SF_CURR_SESS;
3024
0
      _HA_ATOMIC_DEC(&__objt_server(stream->target)->cur_sess);
3025
0
    }
3026
3027
0
    sess_change_server(stream, NULL);
3028
0
    if (may_dequeue_tasks(objt_server(stream->target), stream->be))
3029
0
      process_srv_queue(objt_server(stream->target));
3030
0
  }
3031
3032
  /* shutw is enough to stop a connecting socket */
3033
0
  stream->scb->flags |= SC_FL_ERROR | SC_FL_NOLINGER;
3034
0
  sc_shutdown(stream->scb);
3035
3036
0
  stream->scb->state = SC_ST_CLO;
3037
0
  if (stream->srv_error)
3038
0
    stream->srv_error(stream, stream->scb);
3039
0
}
3040
3041
/* dumps an error message for type <type> at ptr <ptr> related to stream <s>,
3042
 * having reached loop rate <rate>, then aborts hoping to retrieve a core.
3043
 */
3044
void stream_dump_and_crash(enum obj_type *obj, int rate)
3045
0
{
3046
0
  struct stream *s;
3047
0
  char *msg = NULL;
3048
0
  const void *ptr;
3049
3050
0
  ptr = s = objt_stream(obj);
3051
0
  if (!s) {
3052
0
    const struct appctx *appctx = objt_appctx(obj);
3053
0
    if (!appctx)
3054
0
      return;
3055
0
    ptr = appctx;
3056
0
    s = appctx_strm(appctx);
3057
0
    if (!s)
3058
0
      return;
3059
0
  }
3060
3061
0
  chunk_reset(&trash);
3062
0
  chunk_printf(&trash, "  ");
3063
0
  strm_dump_to_buffer(&trash, s, " ", HA_ATOMIC_LOAD(&global.anon_key));
3064
3065
0
  if (ptr != s) { // that's an appctx
3066
0
    const struct appctx *appctx = ptr;
3067
3068
0
    chunk_appendf(&trash, " applet=%p(", appctx->applet);
3069
0
    resolve_sym_name(&trash, NULL, appctx->applet);
3070
0
    chunk_appendf(&trash, ")");
3071
3072
0
    chunk_appendf(&trash, " handler=%p(", appctx->applet->fct);
3073
0
    resolve_sym_name(&trash, NULL, appctx->applet->fct);
3074
0
    chunk_appendf(&trash, ")");
3075
0
  }
3076
3077
0
  memprintf(&msg,
3078
0
            "A bogus %s [%p] is spinning at %d calls per second and refuses to die, "
3079
0
            "aborting now! Please report this error to developers:\n"
3080
0
            "%s\n",
3081
0
            obj_type_name(obj), ptr, rate, trash.area);
3082
3083
0
  ha_alert("%s", msg);
3084
0
  send_log(NULL, LOG_EMERG, "%s", msg);
3085
0
  ABORT_NOW();
3086
0
}
3087
3088
/* initialize the require structures */
3089
static void init_stream()
3090
0
{
3091
0
  int thr;
3092
3093
0
  for (thr = 0; thr < MAX_THREADS; thr++)
3094
0
    LIST_INIT(&ha_thread_ctx[thr].streams);
3095
0
}
3096
INITCALL0(STG_INIT, init_stream);
3097
3098
/************************************************************************/
3099
/*           All supported ACL keywords must be declared here.          */
3100
/************************************************************************/
3101
static enum act_return stream_action_set_retries(struct act_rule *rule, struct proxy *px,
3102
               struct session *sess, struct stream *s, int flags)
3103
0
{
3104
0
  struct sample *smp;
3105
3106
0
  if (!rule->arg.expr_int.expr)
3107
0
    s->max_retries = rule->arg.expr_int.value;
3108
0
  else  {
3109
0
    smp = sample_fetch_as_type(px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.expr_int.expr, SMP_T_SINT);
3110
0
    if (!smp || smp->data.u.sint < 0 || smp->data.u.sint > 100)
3111
0
      goto end;
3112
0
    s->max_retries = smp->data.u.sint;
3113
0
  }
3114
3115
0
  end:
3116
0
  return ACT_RET_CONT;
3117
0
}
3118
3119
3120
/* Parse a "set-retries" action. It takes the level value as argument. It
3121
 * returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
3122
 */
3123
static enum act_parse_ret stream_parse_set_retries(const char **args, int *cur_arg, struct proxy *px,
3124
               struct act_rule *rule, char **err)
3125
0
{
3126
0
  struct sample_expr *expr;
3127
0
  char *endp;
3128
0
  unsigned int where;
3129
3130
0
  if (!*args[*cur_arg]) {
3131
0
    bad_retries:
3132
0
    memprintf(err, "expects exactly 1 argument (an expression or an integer between 1 and 100)");
3133
0
    return ACT_RET_PRS_ERR;
3134
0
  }
3135
0
  if (!(px->cap & PR_CAP_BE)) {
3136
0
    memprintf(err, "'%s' only available in backend or listen section", args[0]);
3137
0
    return ACT_RET_PRS_ERR;
3138
0
  }
3139
0
  if (px->cap & PR_CAP_DEF) {
3140
0
    memprintf(err, "'%s' is not allowed in 'defaults' sections", args[0]);
3141
0
    return ACT_RET_PRS_ERR;
3142
0
  }
3143
3144
  /* value may be either an unsigned integer or an expression */
3145
0
  rule->arg.expr_int.expr = NULL;
3146
0
  rule->arg.expr_int.value = strtol(args[*cur_arg], &endp, 0);
3147
0
  if (*endp == '\0') {
3148
0
    if (rule->arg.expr_int.value < 0  || rule->arg.expr_int.value > 100) {
3149
0
      memprintf(err, "expects an expression or an integer between 1 and 100");
3150
0
      return ACT_RET_PRS_ERR;
3151
0
    }
3152
    /* valid unsigned integer */
3153
0
    (*cur_arg)++;
3154
0
  }
3155
0
  else {   /* invalid unsigned integer, fallback to expr */
3156
0
    expr = sample_parse_expr((char **)args, cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
3157
0
    if (!expr)
3158
0
      return ACT_RET_PRS_ERR;
3159
0
    where = 0;
3160
0
    if (px->cap & PR_CAP_FE)
3161
0
      where |= SMP_VAL_FE_HRQ_HDR;
3162
0
    if (px->cap & PR_CAP_BE)
3163
0
      where |= SMP_VAL_BE_HRQ_HDR;
3164
3165
0
    if (!(expr->fetch->val & where)) {
3166
0
      memprintf(err,
3167
0
          "fetch method '%s' extracts information from '%s', none of which is available here",
3168
0
          args[*cur_arg-1], sample_src_names(expr->fetch->use));
3169
0
      free(expr);
3170
0
      return ACT_RET_PRS_ERR;
3171
0
    }
3172
0
    rule->arg.expr_int.expr = expr;
3173
0
  }
3174
3175
  /* Register processing function. */
3176
0
  rule->action = ACT_CUSTOM;
3177
0
  rule->action_ptr = stream_action_set_retries;
3178
0
  rule->release_ptr = release_expr_int_action;
3179
0
  return ACT_RET_PRS_OK;
3180
0
}
3181
3182
static enum act_return stream_action_set_log_level(struct act_rule *rule, struct proxy *px,
3183
               struct session *sess, struct stream *s, int flags)
3184
0
{
3185
0
  s->logs.level = (uintptr_t)rule->arg.act.p[0];
3186
0
  return ACT_RET_CONT;
3187
0
}
3188
3189
3190
/* Parse a "set-log-level" action. It takes the level value as argument. It
3191
 * returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
3192
 */
3193
static enum act_parse_ret stream_parse_set_log_level(const char **args, int *cur_arg, struct proxy *px,
3194
                 struct act_rule *rule, char **err)
3195
0
{
3196
0
  int level;
3197
3198
0
  if (!*args[*cur_arg]) {
3199
0
    bad_log_level:
3200
0
    memprintf(err, "expects exactly 1 argument (log level name or 'silent')");
3201
0
    return ACT_RET_PRS_ERR;
3202
0
  }
3203
0
  if (strcmp(args[*cur_arg], "silent") == 0)
3204
0
    level = -1;
3205
0
  else if ((level = get_log_level(args[*cur_arg]) + 1) == 0)
3206
0
    goto bad_log_level;
3207
3208
0
  (*cur_arg)++;
3209
3210
  /* Register processing function. */
3211
0
  rule->action_ptr = stream_action_set_log_level;
3212
0
  rule->action = ACT_CUSTOM;
3213
0
  rule->arg.act.p[0] = (void *)(uintptr_t)level;
3214
0
  return ACT_RET_PRS_OK;
3215
0
}
3216
3217
static enum act_return stream_action_set_nice(struct act_rule *rule, struct proxy *px,
3218
                struct session *sess, struct stream *s, int flags)
3219
0
{
3220
0
  s->task->nice = (uintptr_t)rule->arg.act.p[0];
3221
0
  return ACT_RET_CONT;
3222
0
}
3223
3224
3225
/* Parse a "set-nice" action. It takes the nice value as argument. It returns
3226
 * ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
3227
 */
3228
static enum act_parse_ret stream_parse_set_nice(const char **args, int *cur_arg, struct proxy *px,
3229
            struct act_rule *rule, char **err)
3230
0
{
3231
0
  int nice;
3232
3233
0
  if (!*args[*cur_arg]) {
3234
0
    bad_log_level:
3235
0
    memprintf(err, "expects exactly 1 argument (integer value)");
3236
0
    return ACT_RET_PRS_ERR;
3237
0
  }
3238
3239
0
  nice = atoi(args[*cur_arg]);
3240
0
  if (nice < -1024)
3241
0
    nice = -1024;
3242
0
  else if (nice > 1024)
3243
0
    nice = 1024;
3244
3245
0
  (*cur_arg)++;
3246
3247
  /* Register processing function. */
3248
0
  rule->action_ptr = stream_action_set_nice;
3249
0
  rule->action = ACT_CUSTOM;
3250
0
  rule->arg.act.p[0] = (void *)(uintptr_t)nice;
3251
0
  return ACT_RET_PRS_OK;
3252
0
}
3253
3254
3255
static enum act_return tcp_action_switch_stream_mode(struct act_rule *rule, struct proxy *px,
3256
              struct session *sess, struct stream *s, int flags)
3257
0
{
3258
0
  enum pr_mode mode = (uintptr_t)rule->arg.act.p[0];
3259
0
  const struct mux_proto_list *mux_proto = rule->arg.act.p[1];
3260
3261
0
  if (!IS_HTX_STRM(s) && mode == PR_MODE_HTTP) {
3262
0
    if (!stream_set_http_mode(s, mux_proto)) {
3263
0
      stream_abort(s);
3264
0
      return ACT_RET_ABRT;
3265
0
    }
3266
0
  }
3267
0
  return ACT_RET_STOP;
3268
0
}
3269
3270
3271
static int check_tcp_switch_stream_mode(struct act_rule *rule, struct proxy *px, char **err)
3272
0
{
3273
0
  const struct mux_proto_list *mux_ent;
3274
0
  const struct mux_proto_list *mux_proto = rule->arg.act.p[1];
3275
0
  enum pr_mode pr_mode = (uintptr_t)rule->arg.act.p[0];
3276
0
  enum proto_proxy_mode mode = conn_pr_mode_to_proto_mode(pr_mode);
3277
3278
0
  if (pr_mode == PR_MODE_HTTP)
3279
0
    px->options |= PR_O_HTTP_UPG;
3280
3281
0
  if (mux_proto) {
3282
0
    mux_ent = conn_get_best_mux_entry(mux_proto->mux_proto, IST_NULL, PROTO_SIDE_FE, 0, mode);
3283
0
    if (!mux_ent || !isteq(mux_ent->mux_proto, mux_proto->mux_proto)) {
3284
0
      memprintf(err, "MUX protocol '%.*s' is not compatible with the selected mode",
3285
0
          (int)mux_proto->mux_proto.len, mux_proto->mux_proto.ptr);
3286
0
      return 0;
3287
0
    }
3288
0
  }
3289
0
  else {
3290
0
    mux_ent = conn_get_best_mux_entry(IST_NULL, IST_NULL, PROTO_SIDE_FE, 0, mode);
3291
0
    if (!mux_ent) {
3292
0
      memprintf(err, "Unable to find compatible MUX protocol with the selected mode");
3293
0
      return 0;
3294
0
    }
3295
0
  }
3296
3297
  /* Update the mux */
3298
0
  rule->arg.act.p[1] = (void *)mux_ent;
3299
0
  return 1;
3300
3301
0
}
3302
3303
static enum act_parse_ret stream_parse_switch_mode(const char **args, int *cur_arg,
3304
               struct proxy *px, struct act_rule *rule,
3305
               char **err)
3306
0
{
3307
0
  const struct mux_proto_list *mux_proto = NULL;
3308
0
  struct ist proto;
3309
0
  enum pr_mode mode;
3310
3311
  /* must have at least the mode */
3312
0
  if (*(args[*cur_arg]) == 0) {
3313
0
    memprintf(err, "'%s %s' expects a mode as argument.", args[0], args[*cur_arg-1]);
3314
0
    return ACT_RET_PRS_ERR;
3315
0
  }
3316
3317
0
  if (!(px->cap & PR_CAP_FE)) {
3318
0
    memprintf(err, "'%s %s' not allowed because %s '%s' has no frontend capability",
3319
0
        args[0], args[*cur_arg-1], proxy_type_str(px), px->id);
3320
0
    return ACT_RET_PRS_ERR;
3321
0
  }
3322
  /* Check if the mode. For now "tcp" is disabled because downgrade is not
3323
   * supported and PT is the only TCP mux.
3324
   */
3325
0
  if (strcmp(args[*cur_arg], "http") == 0)
3326
0
    mode = PR_MODE_HTTP;
3327
0
  else {
3328
0
    memprintf(err, "'%s %s' expects a valid mode (got '%s').", args[0], args[*cur_arg-1], args[*cur_arg]);
3329
0
    return ACT_RET_PRS_ERR;
3330
0
  }
3331
3332
  /* check the proto, if specified */
3333
0
  if (*(args[*cur_arg+1]) && strcmp(args[*cur_arg+1], "proto") == 0) {
3334
0
    if (*(args[*cur_arg+2]) == 0) {
3335
0
      memprintf(err, "'%s %s': '%s' expects a protocol as argument.",
3336
0
          args[0], args[*cur_arg-1], args[*cur_arg+1]);
3337
0
      return ACT_RET_PRS_ERR;
3338
0
    }
3339
3340
0
    proto = ist(args[*cur_arg + 2]);
3341
0
    mux_proto = get_mux_proto(proto);
3342
0
    if (!mux_proto) {
3343
0
      memprintf(err, "'%s %s': '%s' expects a valid MUX protocol, if specified (got '%s')",
3344
0
          args[0], args[*cur_arg-1], args[*cur_arg+1], args[*cur_arg+2]);
3345
0
      return ACT_RET_PRS_ERR;
3346
0
    }
3347
0
    *cur_arg += 2;
3348
0
  }
3349
3350
0
  (*cur_arg)++;
3351
3352
  /* Register processing function. */
3353
0
  rule->action_ptr = tcp_action_switch_stream_mode;
3354
0
  rule->check_ptr  = check_tcp_switch_stream_mode;
3355
0
  rule->action = ACT_CUSTOM;
3356
0
  rule->arg.act.p[0] = (void *)(uintptr_t)mode;
3357
0
  rule->arg.act.p[1] = (void *)mux_proto;
3358
0
  return ACT_RET_PRS_OK;
3359
0
}
3360
3361
/* 0=OK, <0=Alert, >0=Warning */
3362
static enum act_parse_ret stream_parse_use_service(const char **args, int *cur_arg,
3363
                                                   struct proxy *px, struct act_rule *rule,
3364
                                                   char **err)
3365
0
{
3366
0
  struct action_kw *kw;
3367
3368
  /* Check if the service name exists. */
3369
0
  if (*(args[*cur_arg]) == 0) {
3370
0
    memprintf(err, "'%s' expects a service name.", args[0]);
3371
0
    return ACT_RET_PRS_ERR;
3372
0
  }
3373
3374
  /* lookup for keyword corresponding to a service. */
3375
0
  kw = action_lookup(&service_keywords, args[*cur_arg]);
3376
0
  if (!kw) {
3377
0
    memprintf(err, "'%s' unknown service name.", args[1]);
3378
0
    return ACT_RET_PRS_ERR;
3379
0
  }
3380
0
  (*cur_arg)++;
3381
3382
  /* executes specific rule parser. */
3383
0
  rule->kw = kw;
3384
0
  if (kw->parse((const char **)args, cur_arg, px, rule, err) == ACT_RET_PRS_ERR)
3385
0
    return ACT_RET_PRS_ERR;
3386
3387
  /* Register processing function. */
3388
0
  rule->action_ptr = process_use_service;
3389
0
  rule->action = ACT_CUSTOM;
3390
3391
0
  return ACT_RET_PRS_OK;
3392
0
}
3393
3394
void service_keywords_register(struct action_kw_list *kw_list)
3395
0
{
3396
0
  act_add_list(&service_keywords, kw_list);
3397
0
}
3398
3399
struct action_kw *service_find(const char *kw)
3400
0
{
3401
0
  return action_lookup(&service_keywords, kw);
3402
0
}
3403
3404
/* Lists the known services on <out>. If <out> is null, emit them on stdout one
3405
 * per line.
3406
 */
3407
void list_services(FILE *out)
3408
0
{
3409
0
  const struct action_kw *akwp, *akwn;
3410
0
  struct action_kw_list *kw_list;
3411
0
  int found = 0;
3412
0
  int i;
3413
3414
0
  if (out)
3415
0
    fprintf(out, "Available services :");
3416
3417
0
  for (akwn = akwp = NULL;; akwp = akwn) {
3418
0
    list_for_each_entry(kw_list, &service_keywords, list) {
3419
0
      for (i = 0; kw_list->kw[i].kw != NULL; i++) {
3420
0
        if (strordered(akwp ? akwp->kw : NULL,
3421
0
                 kw_list->kw[i].kw,
3422
0
                 akwn != akwp ? akwn->kw : NULL))
3423
0
          akwn = &kw_list->kw[i];
3424
0
        found = 1;
3425
0
      }
3426
0
    }
3427
0
    if (akwn == akwp)
3428
0
      break;
3429
0
    if (out)
3430
0
      fprintf(out, " %s", akwn->kw);
3431
0
    else
3432
0
      printf("%s\n", akwn->kw);
3433
0
  }
3434
0
  if (!found && out)
3435
0
    fprintf(out, " none\n");
3436
0
}
3437
3438
/* appctx context used by the "show sess" command */
3439
/* flags used for show_sess_ctx.flags */
3440
0
#define CLI_SHOWSESS_F_SUSP     0x00000001   /* show only suspicious streams */
3441
0
#define CLI_SHOWSESS_F_DUMP_URI 0x00000002   /* Dump TXN's uri if available in dump */
3442
0
#define CLI_SHOWSESS_F_SERVER   0x00000004   /* show only streams attached to this server */
3443
0
#define CLI_SHOWSESS_F_BACKEND  0x00000008   /* show only streams attached to this backend */
3444
0
#define CLI_SHOWSESS_F_FRONTEND 0x00000010   /* show only streams attached to this frontend */
3445
3446
struct show_sess_ctx {
3447
  struct bref bref; /* back-reference from the session being dumped */
3448
  void *target;   /* session we want to dump, or NULL for all */
3449
  void *filter;           /* element to filter on (e.g. server if CLI_SHOWSESS_F_SERVER) */
3450
  unsigned int thr;       /* the thread number being explored (0..MAX_THREADS-1) */
3451
  unsigned int uid; /* if non-null, the uniq_id of the session being dumped */
3452
  unsigned int min_age;   /* minimum age of streams to dump */
3453
  unsigned int flags;     /* CLI_SHOWSESS_* */
3454
  int section;    /* section of the session being dumped */
3455
  int pos;    /* last position of the current session's buffer */
3456
};
3457
3458
/* This function appends a complete dump of a stream state onto the buffer,
3459
 * possibly anonymizing using the specified anon_key. The caller is responsible
3460
 * for ensuring that enough room remains in the buffer to dump a complete stream
3461
 * at once. Each new output line will be prefixed with <pfx> if non-null, which
3462
 * is used to preserve indenting. The context <ctx>, if non-null, will be used
3463
 * to customize the dump.
3464
 */
3465
static void __strm_dump_to_buffer(struct buffer *buf, const struct show_sess_ctx *ctx,
3466
          const struct stream *strm, const char *pfx, uint32_t anon_key)
3467
0
{
3468
0
  struct stconn *scf, *scb;
3469
0
  struct tm tm;
3470
0
  extern const char *monthname[12];
3471
0
  char pn[INET6_ADDRSTRLEN];
3472
0
  struct connection *conn;
3473
0
  struct appctx *tmpctx;
3474
0
  uint64_t request_ts;
3475
3476
0
  pfx = pfx ? pfx : "";
3477
3478
0
  if (th_ctx->flags & TH_FL_IN_ANY_HANDLER) {
3479
    /* avoid calling localtime_r() to avoid a risk of deadlock if we
3480
     * interrupted libc for example, cf
3481
     * https://github.com/haproxy/haproxy/issues/2861#issuecomment-2677761037
3482
     */
3483
0
    chunk_appendf(buf, "%p: [%lu.%06lu]", strm,
3484
0
            (ulong)strm->logs.accept_date.tv_sec,
3485
0
            (ulong)strm->logs.accept_date.tv_usec);
3486
0
  } else {
3487
0
    get_localtime(strm->logs.accept_date.tv_sec, &tm);
3488
0
    chunk_appendf(buf,
3489
0
            "%p: [%02d/%s/%04d:%02d:%02d:%02d.%06lu]",
3490
0
            strm,
3491
0
            tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
3492
0
            tm.tm_hour, tm.tm_min, tm.tm_sec, (ulong)strm->logs.accept_date.tv_usec);
3493
0
  }
3494
3495
0
  chunk_appendf(buf, " id=%u proto=%s",
3496
0
         strm->uniq_id, strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
3497
3498
0
  conn = objt_conn(strm_orig(strm));
3499
3500
  /* be careful not to allocate RAM from a signal handler! */
3501
0
  if (conn && !conn->src && !(th_ctx->flags & TH_FL_IN_ANY_HANDLER))
3502
0
    conn_get_src(conn);
3503
3504
0
  switch (conn && conn->src ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
3505
0
  case AF_INET:
3506
0
  case AF_INET6:
3507
0
    chunk_appendf(buf, " source=%s:%d\n",
3508
0
                  HA_ANON_STR(anon_key, pn), get_host_port(conn->src));
3509
0
    break;
3510
0
  case AF_UNIX:
3511
0
  case AF_CUST_ABNS:
3512
0
  case AF_CUST_ABNSZ:
3513
0
    chunk_appendf(buf, " source=unix:%d\n", strm_li(strm)->luid);
3514
0
    break;
3515
0
  default:
3516
    /* no more information to print right now */
3517
0
    chunk_appendf(buf, "\n");
3518
0
    break;
3519
0
  }
3520
3521
0
  chunk_appendf(buf,
3522
0
         "%s  flags=0x%x, conn_retries=%d, conn_exp=%s conn_et=0x%03x srv_conn=%p, pend_pos=%p waiting=%d epoch=%#x\n", pfx,
3523
0
         strm->flags, strm->conn_retries,
3524
0
         strm->conn_exp ?
3525
0
                 tick_is_expired(strm->conn_exp, now_ms) ? "<PAST>" :
3526
0
                         human_time(TICKS_TO_MS(strm->conn_exp - now_ms),
3527
0
                         TICKS_TO_MS(1000)) : "<NEVER>",
3528
0
         strm->conn_err_type, strm->srv_conn, strm->pend_pos,
3529
0
         LIST_INLIST(&strm->buffer_wait.list), strm->stream_epoch);
3530
3531
0
  chunk_appendf(buf, "%s  p_con=%u p_stc=%u p_req=%u p_res=%u p_prp=%u\n", pfx,
3532
0
          strm->passes_connect, strm->passes_stconn, strm->passes_reqana, strm->passes_resana, strm->passes_propag);
3533
3534
0
  chunk_appendf(buf,
3535
0
         "%s  frontend=%s (id=%u mode=%s), listener=%s (id=%u)", pfx,
3536
0
         HA_ANON_STR(anon_key, strm_fe(strm)->id), strm_fe(strm)->uuid, proxy_mode_str(strm_fe(strm)->mode),
3537
0
         strm_li(strm) ? strm_li(strm)->name ? strm_li(strm)->name : "?" : "?",
3538
0
         strm_li(strm) ? strm_li(strm)->luid : 0);
3539
3540
  /* be careful not to allocate RAM from a signal handler! */
3541
0
  if (conn && !conn->dst && !(th_ctx->flags & TH_FL_IN_ANY_HANDLER))
3542
0
    conn_get_dst(conn);
3543
3544
0
  switch (conn && conn->dst ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
3545
0
  case AF_INET:
3546
0
  case AF_INET6:
3547
0
    chunk_appendf(buf, " addr=%s:%d\n",
3548
0
           HA_ANON_STR(anon_key, pn), get_host_port(conn->dst));
3549
0
    break;
3550
0
  case AF_UNIX:
3551
0
  case AF_CUST_ABNS:
3552
0
  case AF_CUST_ABNSZ:
3553
0
    chunk_appendf(buf, " addr=unix:%d\n", strm_li(strm)->luid);
3554
0
    break;
3555
0
  default:
3556
    /* no more information to print right now */
3557
0
    chunk_appendf(buf, "\n");
3558
0
    break;
3559
0
  }
3560
3561
0
  if (strm->be->cap & PR_CAP_BE)
3562
0
    chunk_appendf(buf,
3563
0
           "%s  backend=%s (id=%u mode=%s)", pfx,
3564
0
           HA_ANON_STR(anon_key, strm->be->id),
3565
0
           strm->be->uuid, proxy_mode_str(strm->be->mode));
3566
0
  else
3567
0
    chunk_appendf(buf, "%s  backend=<NONE> (id=-1 mode=-)", pfx);
3568
3569
0
  conn = sc_conn(strm->scb);
3570
3571
  /* be careful not to allocate RAM from a signal handler! */
3572
0
  if (conn && !conn->src && !(th_ctx->flags & TH_FL_IN_ANY_HANDLER))
3573
0
    conn_get_src(conn);
3574
3575
0
  switch (conn && conn->src ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
3576
0
  case AF_INET:
3577
0
  case AF_INET6:
3578
0
    chunk_appendf(buf, " addr=%s:%d\n",
3579
0
           HA_ANON_STR(anon_key, pn), get_host_port(conn->src));
3580
0
    break;
3581
0
  case AF_UNIX:
3582
0
  case AF_CUST_ABNS:
3583
0
  case AF_CUST_ABNSZ:
3584
0
    chunk_appendf(buf, " addr=unix\n");
3585
0
    break;
3586
0
  default:
3587
    /* no more information to print right now */
3588
0
    chunk_appendf(buf, "\n");
3589
0
    break;
3590
0
  }
3591
3592
0
  if (strm->be->cap & PR_CAP_BE)
3593
0
    chunk_appendf(buf,
3594
0
           "%s  server=%s (id=%u)", pfx,
3595
0
           objt_server(strm->target) ? HA_ANON_STR(anon_key, __objt_server(strm->target)->id) : "<none>",
3596
0
           objt_server(strm->target) ? __objt_server(strm->target)->puid : 0);
3597
0
  else
3598
0
    chunk_appendf(buf, "%s  server=<NONE> (id=-1)", pfx);
3599
3600
  /* be careful not to allocate RAM from a signal handler! */
3601
0
  if (conn && !conn->dst && !(th_ctx->flags & TH_FL_IN_ANY_HANDLER))
3602
0
    conn_get_dst(conn);
3603
3604
0
  switch (conn && conn->dst ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
3605
0
  case AF_INET:
3606
0
  case AF_INET6:
3607
0
    chunk_appendf(buf, " addr=%s:%d\n",
3608
0
           HA_ANON_STR(anon_key, pn), get_host_port(conn->dst));
3609
0
    break;
3610
0
  case AF_UNIX:
3611
0
  case AF_CUST_ABNS:
3612
0
  case AF_CUST_ABNSZ:
3613
0
    chunk_appendf(buf, " addr=unix\n");
3614
0
    break;
3615
0
  default:
3616
    /* no more information to print right now */
3617
0
    chunk_appendf(buf, "\n");
3618
0
    break;
3619
0
  }
3620
3621
0
  chunk_appendf(buf,
3622
0
          "%s  task=%p (state=0x%02x nice=%d calls=%u rate=%u exp=%s tid=%d(%d/%d)%s", pfx,
3623
0
         strm->task,
3624
0
         strm->task->state,
3625
0
         strm->task->nice, strm->task->calls,
3626
0
         read_freq_ctr_period_estimate(&strm->call_rate, MS_TO_TICKS(1000)),
3627
0
         strm->task->expire ?
3628
0
                 tick_is_expired(strm->task->expire, now_ms) ? "<PAST>" :
3629
0
                         human_time(TICKS_TO_MS(strm->task->expire - now_ms),
3630
0
                         TICKS_TO_MS(1000)) : "<NEVER>",
3631
0
               strm->task->tid,
3632
0
               ha_thread_info[strm->task->tid].tgid,
3633
0
               ha_thread_info[strm->task->tid].ltid,
3634
0
         task_in_rq(strm->task) ? ", running" : "");
3635
3636
0
  request_ts = strm->logs.accept_ts;
3637
0
  request_ts += ms_to_ns(strm->logs.t_idle >= 0 ? strm->logs.t_idle + strm->logs.t_handshake : 0);
3638
0
  chunk_appendf(buf,
3639
0
          " age=%s)\n",
3640
0
          human_time(ns_to_sec(now_ns) - ns_to_sec(request_ts), 1));
3641
3642
0
  if ((strm->flags & SF_TXN_MASK) == SF_TXN_HTTP) {
3643
0
    chunk_appendf(buf,
3644
0
          "%s  txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s req.f=0x%02x rsp.f=0x%02x", pfx,
3645
0
          strm->txn.http, strm->txn.http->flags,
3646
0
          strm->txn.http->meth, strm->txn.http->status,
3647
0
          h1_msg_state_str(strm->txn.http->req.msg_state),
3648
0
          h1_msg_state_str(strm->txn.http->rsp.msg_state),
3649
0
          strm->txn.http->req.flags, strm->txn.http->rsp.flags);
3650
0
    if (ctx && (ctx->flags & CLI_SHOWSESS_F_DUMP_URI) && strm->txn.http->uri)
3651
0
      chunk_appendf(buf, " uri=\"%s\"",
3652
0
              HA_ANON_STR(anon_key, strm->txn.http->uri));
3653
0
    chunk_memcat(buf, "\n", 1);
3654
0
  }
3655
3656
0
  scf = strm->scf;
3657
0
  chunk_appendf(buf, "%s  scf=%p flags=0x%08x ioto=%s state=%s endp=%s,%p,0x%08x sub=%d in=%llu out=%llu", pfx,
3658
0
          scf, scf->flags, human_time(scf->ioto, TICKS_TO_MS(1000)), sc_state_str(scf->state),
3659
0
          (sc_ep_test(scf, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scf, SE_FL_T_APPLET) ? "APPCTX" : "NONE")),
3660
0
          scf->sedesc->se, sc_ep_get(scf), scf->wait_event.events, scf->bytes_in, scf->bytes_out);
3661
0
  chunk_appendf(buf, " rex=%s",
3662
0
          sc_ep_rcv_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scf) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3663
0
  chunk_appendf(buf, " wex=%s",
3664
0
          sc_ep_snd_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scf) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3665
0
  chunk_appendf(buf, " rto=%s",
3666
0
          tick_isset(scf->sedesc->lra) ? human_time(TICKS_TO_MS(tick_add(scf->sedesc->lra, scf->ioto) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3667
0
  chunk_appendf(buf, " wto=%s\n",
3668
0
          tick_isset(scf->sedesc->fsb) ? human_time(TICKS_TO_MS(tick_add(scf->sedesc->fsb, scf->ioto) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3669
3670
0
  chunk_appendf(&trash, "%s    iobuf.flags=0x%08x .pipe=%d .buf=%u@%p+%u/%u\n", pfx,
3671
0
          scf->sedesc->iobuf.flags,
3672
0
          scf->sedesc->iobuf.pipe ? scf->sedesc->iobuf.pipe->data : 0,
3673
0
          scf->sedesc->iobuf.buf ? (unsigned int)b_data(scf->sedesc->iobuf.buf): 0,
3674
0
          scf->sedesc->iobuf.buf ? b_orig(scf->sedesc->iobuf.buf): NULL,
3675
0
          scf->sedesc->iobuf.buf ? (unsigned int)b_head_ofs(scf->sedesc->iobuf.buf): 0,
3676
0
          scf->sedesc->iobuf.buf ? (unsigned int)b_size(scf->sedesc->iobuf.buf): 0);
3677
3678
0
  if ((conn = sc_conn(scf)) != NULL) {
3679
0
    if (conn->mux && conn->mux->show_sd) {
3680
0
      char muxpfx[100] = "";
3681
3682
0
      snprintf(muxpfx, sizeof(muxpfx), "%s      ", pfx);
3683
0
      chunk_appendf(buf, "%s     ", pfx);
3684
0
      conn->mux->show_sd(buf, scf->sedesc, muxpfx);
3685
0
      chunk_appendf(buf, "\n");
3686
0
    }
3687
3688
0
    chunk_appendf(buf,
3689
0
                  "%s      co0=%p ctrl=%s xprt=%s mux=%s target=%s:%p\n", pfx,
3690
0
            conn,
3691
0
            conn_get_ctrl_name(conn),
3692
0
            conn_get_xprt_name(conn),
3693
0
            conn_get_mux_name(conn),
3694
0
                  obj_type_name(conn->target),
3695
0
                  obj_base_ptr(conn->target));
3696
3697
0
    chunk_appendf(buf,
3698
0
                  "%s      flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", pfx,
3699
0
                  conn->flags,
3700
0
                  conn_fd(conn),
3701
0
                  conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0,
3702
0
                  conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0,
3703
0
            conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0);
3704
0
  }
3705
0
  else if ((tmpctx = sc_appctx(scf)) != NULL) {
3706
0
    chunk_appendf(buf,
3707
0
                  "%s      app0=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", pfx,
3708
0
            tmpctx,
3709
0
            tmpctx->st0,
3710
0
            tmpctx->st1,
3711
0
                  tmpctx->applet->name,
3712
0
                  tmpctx->t->tid,
3713
0
                  tmpctx->t->nice, tmpctx->t->calls,
3714
0
            read_freq_ctr_period_estimate(&tmpctx->call_rate, MS_TO_TICKS(1000)));
3715
0
  }
3716
3717
0
  scb = strm->scb;
3718
0
  chunk_appendf(buf, "%s  scb=%p flags=0x%08x ioto=%s state=%s endp=%s,%p,0x%08x sub=%d in=%llu out=%llu", pfx,
3719
0
          scb, scb->flags, human_time(scb->ioto, TICKS_TO_MS(1000)), sc_state_str(scb->state),
3720
0
          (sc_ep_test(scb, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scb, SE_FL_T_APPLET) ? "APPCTX" : "NONE")),
3721
0
          scb->sedesc->se, sc_ep_get(scb), scb->wait_event.events, scb->bytes_in, scb->bytes_out);
3722
0
  chunk_appendf(buf, " rex=%s",
3723
0
          sc_ep_rcv_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scb) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3724
0
  chunk_appendf(buf, " wex=%s",
3725
0
          sc_ep_snd_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scb) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3726
0
  chunk_appendf(buf, " rto=%s",
3727
0
          tick_isset(scb->sedesc->lra) ? human_time(TICKS_TO_MS(tick_add(scb->sedesc->lra, scb->ioto) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3728
0
  chunk_appendf(buf, " wto=%s\n",
3729
0
          tick_isset(scb->sedesc->fsb) ? human_time(TICKS_TO_MS(tick_add(scb->sedesc->fsb, scb->ioto) - now_ms), TICKS_TO_MS(1000)) : "<NEVER>");
3730
3731
0
  chunk_appendf(&trash, "%s    iobuf.flags=0x%08x .pipe=%d .buf=%u@%p+%u/%u\n", pfx,
3732
0
          scb->sedesc->iobuf.flags,
3733
0
          scb->sedesc->iobuf.pipe ? scb->sedesc->iobuf.pipe->data : 0,
3734
0
          scb->sedesc->iobuf.buf ? (unsigned int)b_data(scb->sedesc->iobuf.buf): 0,
3735
0
          scb->sedesc->iobuf.buf ? b_orig(scb->sedesc->iobuf.buf): NULL,
3736
0
          scb->sedesc->iobuf.buf ? (unsigned int)b_head_ofs(scb->sedesc->iobuf.buf): 0,
3737
0
          scb->sedesc->iobuf.buf ? (unsigned int)b_size(scb->sedesc->iobuf.buf): 0);
3738
3739
0
  if ((conn = sc_conn(scb)) != NULL) {
3740
0
    if (conn->mux && conn->mux->show_sd) {
3741
0
      char muxpfx[100] = "";
3742
3743
0
      snprintf(muxpfx, sizeof(muxpfx), "%s      ", pfx);
3744
0
      chunk_appendf(buf, "%s     ", pfx);
3745
0
      conn->mux->show_sd(buf, scb->sedesc, muxpfx);
3746
0
      chunk_appendf(buf, "\n");
3747
0
    }
3748
3749
0
    chunk_appendf(buf,
3750
0
                  "%s      co1=%p ctrl=%s xprt=%s mux=%s target=%s:%p\n", pfx,
3751
0
            conn,
3752
0
            conn_get_ctrl_name(conn),
3753
0
            conn_get_xprt_name(conn),
3754
0
            conn_get_mux_name(conn),
3755
0
                  obj_type_name(conn->target),
3756
0
                  obj_base_ptr(conn->target));
3757
3758
0
    chunk_appendf(buf,
3759
0
                  "%s      flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", pfx,
3760
0
                  conn->flags,
3761
0
                  conn_fd(conn),
3762
0
                  conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0,
3763
0
                  conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0,
3764
0
            conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0);
3765
0
  }
3766
0
  else if ((tmpctx = sc_appctx(scb)) != NULL) {
3767
0
    chunk_appendf(buf,
3768
0
                  "%s      app1=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", pfx,
3769
0
            tmpctx,
3770
0
            tmpctx->st0,
3771
0
            tmpctx->st1,
3772
0
                  tmpctx->applet->name,
3773
0
                  tmpctx->t->tid,
3774
0
                  tmpctx->t->nice, tmpctx->t->calls,
3775
0
            read_freq_ctr_period_estimate(&tmpctx->call_rate, MS_TO_TICKS(1000)));
3776
0
  }
3777
3778
0
  if (HAS_FILTERS(strm)) {
3779
0
    const struct filter *flt;
3780
3781
0
    chunk_appendf(buf, "%s  filters={", pfx);
3782
0
    list_for_each_entry(flt, &strm->strm_flt.filters, list) {
3783
0
      if (flt->list.p != &strm->strm_flt.filters)
3784
0
        chunk_appendf(buf, ", ");
3785
0
      chunk_appendf(buf, "%p=\"%s\" [%u]", flt, FLT_ID(flt), flt->calls);
3786
0
    }
3787
0
    chunk_appendf(buf, "}\n");
3788
0
  }
3789
3790
0
  chunk_appendf(buf,
3791
0
         "%s  req=%p (f=0x%06x an=0x%x tofwd=%d)\n"
3792
0
         "%s      an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n",
3793
0
         pfx,
3794
0
         &strm->req,
3795
0
         strm->req.flags, strm->req.analysers,
3796
0
         strm->req.to_forward,
3797
0
         pfx,
3798
0
         strm->req.analyse_exp ?
3799
0
         human_time(TICKS_TO_MS(strm->req.analyse_exp - now_ms),
3800
0
        TICKS_TO_MS(1000)) : "<NEVER>",
3801
0
         &strm->req.buf,
3802
0
         b_orig(&strm->req.buf), (unsigned int)strm->req.output,
3803
0
         (unsigned int)b_peek_ofs(&strm->req.buf, strm->req.output),
3804
0
         (unsigned int)(c_data(&strm->req) - strm->req.output),
3805
0
         (unsigned int)strm->req.buf.size);
3806
3807
0
  if (IS_HTX_STRM(strm)) {
3808
0
    struct htx *htx = htxbuf(&strm->req.buf);
3809
3810
0
    chunk_appendf(buf,
3811
0
            "%s      htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s\n", pfx,
3812
0
            htx, htx->flags, htx->size, htx->data, htx_nbblks(htx),
3813
0
            (htx->tail >= htx->head) ? "NO" : "YES");
3814
0
  }
3815
0
  if (HAS_FILTERS(strm) && strm->req.flt.current) {
3816
0
    const struct filter *flt = strm->req.flt.current;
3817
3818
0
    chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x %s) \n", pfx,
3819
0
            flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers,
3820
0
            (flt == strm->waiting_entity.ptr) ? "YIELDING" : "RUNNING");
3821
0
  }
3822
3823
0
  chunk_appendf(buf,
3824
0
         "%s  res=%p (f=0x%06x an=0x%x tofwd=%d)\n"
3825
0
         "%s      an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n",
3826
0
         pfx,
3827
0
         &strm->res,
3828
0
         strm->res.flags, strm->res.analysers,
3829
0
         strm->res.to_forward,
3830
0
         pfx,
3831
0
         strm->res.analyse_exp ?
3832
0
         human_time(TICKS_TO_MS(strm->res.analyse_exp - now_ms),
3833
0
        TICKS_TO_MS(1000)) : "<NEVER>",
3834
0
         &strm->res.buf,
3835
0
               b_orig(&strm->res.buf), (unsigned int)strm->res.output,
3836
0
         (unsigned int)b_peek_ofs(&strm->res.buf, strm->res.output),
3837
0
         (unsigned int)(c_data(&strm->res) - strm->res.output),
3838
0
         (unsigned int)strm->res.buf.size);
3839
3840
0
  if (IS_HTX_STRM(strm)) {
3841
0
    struct htx *htx = htxbuf(&strm->res.buf);
3842
3843
0
    chunk_appendf(buf,
3844
0
            "%s      htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s\n", pfx,
3845
0
            htx, htx->flags, htx->size, htx->data, htx_nbblks(htx),
3846
0
            (htx->tail >= htx->head) ? "NO" : "YES");
3847
0
  }
3848
3849
0
  if (HAS_FILTERS(strm) && strm->res.flt.current) {
3850
0
    const struct filter *flt = strm->res.flt.current;
3851
3852
0
    chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x %s) \n", pfx,
3853
0
            flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers,
3854
0
            (flt == strm->waiting_entity.ptr) ? "YIELDING" : "RUNNING");
3855
0
  }
3856
3857
0
  if (strm->current_rule_list && strm->current_rule) {
3858
0
    const struct act_rule *rule = strm->current_rule;
3859
0
    chunk_appendf(buf, "%s  current_rule=\"%s\" [%s:%d] (%s)\n",
3860
0
            pfx, rule->kw ? rule->kw->kw : "?", rule->conf.file, rule->conf.line,
3861
0
            (rule == strm->waiting_entity.ptr) ? "YIELDING" : "RUNNING");
3862
0
  }
3863
0
}
3864
3865
/* Context-less function to append a complete dump of a stream state onto the
3866
 * buffer. It relies on __strm_dump_to_buffer.
3867
 */
3868
void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const char *pfx, uint32_t anon_key)
3869
0
{
3870
0
  __strm_dump_to_buffer(buf, NULL, strm, pfx, anon_key);
3871
0
}
3872
3873
/* This function dumps a complete stream state onto the stream connector's
3874
 * read buffer. The stream has to be set in strm. It returns 0 if the output
3875
 * buffer is full and it needs to be called again, otherwise non-zero. It is
3876
 * designed to be called from stats_dump_strm_to_buffer() below.
3877
 */
3878
static int stats_dump_full_strm_to_buffer(struct appctx *appctx, struct stream *strm)
3879
0
{
3880
0
  struct show_sess_ctx *ctx = appctx->svcctx;
3881
3882
0
  chunk_reset(&trash);
3883
3884
0
  if (ctx->section > 0 && ctx->uid != strm->uniq_id) {
3885
    /* stream changed, no need to go any further */
3886
0
    chunk_appendf(&trash, "  *** session terminated while we were watching it ***\n");
3887
0
    if (applet_putchk(appctx, &trash) == -1)
3888
0
      goto full;
3889
0
    goto done;
3890
0
  }
3891
3892
0
  switch (ctx->section) {
3893
0
  case 0: /* main status of the stream */
3894
0
    ctx->uid = strm->uniq_id;
3895
0
    ctx->section = 1;
3896
0
    __fallthrough;
3897
3898
0
  case 1:
3899
0
    __strm_dump_to_buffer(&trash, ctx, strm, "", appctx->cli_ctx.anon_key);
3900
0
    if (applet_putchk(appctx, &trash) == -1)
3901
0
      goto full;
3902
3903
    /* use other states to dump the contents */
3904
0
  }
3905
  /* end of dump */
3906
0
 done:
3907
0
  ctx->uid = 0;
3908
0
  ctx->section = 0;
3909
0
  return 1;
3910
0
 full:
3911
0
  return 0;
3912
0
}
3913
3914
static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx, void *private)
3915
0
{
3916
0
  struct show_sess_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
3917
0
  int cur_arg = 2;
3918
3919
0
  if (!cli_has_level(appctx, ACCESS_LVL_OPER))
3920
0
    return 1;
3921
3922
  /* now all sessions by default */
3923
0
  ctx->target = NULL;
3924
0
  ctx->min_age = 0;
3925
0
  ctx->section = 0; /* start with stream status */
3926
0
  ctx->pos = 0;
3927
0
  ctx->thr = 0;
3928
3929
0
  if (*args[cur_arg] && strcmp(args[cur_arg], "older") == 0) {
3930
0
    unsigned timeout;
3931
0
    const char *res;
3932
3933
0
    if (!*args[cur_arg+1])
3934
0
      return cli_err(appctx, "Expects a minimum age (in seconds by default).\n");
3935
3936
0
    res = parse_time_err(args[cur_arg+1], &timeout, TIME_UNIT_S);
3937
0
    if (res != 0)
3938
0
      return cli_err(appctx, "Invalid age.\n");
3939
3940
0
    ctx->min_age = timeout;
3941
0
    ctx->target = (void *)-1; /* show all matching entries */
3942
0
    cur_arg +=2;
3943
0
  }
3944
0
  else if (*args[cur_arg] && strcmp(args[cur_arg], "all") == 0) {
3945
0
    ctx->target = (void *)-1;
3946
0
    cur_arg++;
3947
0
  }
3948
0
  else if (*args[cur_arg] && strcmp(args[cur_arg], "help") == 0) {
3949
0
    chunk_printf(&trash,
3950
0
           "Usage: show sess [<id> | all | help] [<options>*]\n"
3951
0
           "Dumps active streams (formerly called 'sessions'). Available selectors:\n"
3952
0
           "   <id>         dump only this stream identifier (0x...)\n"
3953
0
           "   all          dump all matching streams in large format\n"
3954
0
           "   help         show this message\n"
3955
0
           "   susp         report streams considered suspicious\n"
3956
0
           "Available options: \n"
3957
0
           "   show-uri     also display the transaction URI, if available\n"
3958
0
           "   older <age>  only display streams older than <age> seconds\n"
3959
0
           "   server <b/s> only show streams attached to this backend+server\n"
3960
0
           "   backend <b>  only show streams attached to this backend\n"
3961
0
           "   frontend <f> only show streams attached to this frontend\n"
3962
0
           "Without any argument, all streams are dumped in a shorter format.");
3963
0
    return cli_err(appctx, trash.area);
3964
0
  }
3965
0
  else if (*args[cur_arg]) {
3966
0
    ctx->target = (void *)strtoul(args[cur_arg], NULL, 0);
3967
0
    if (ctx->target)
3968
0
      cur_arg++;
3969
0
  }
3970
3971
  /* show-sess options parsing */
3972
0
  while (*args[cur_arg]) {
3973
0
    if (*args[cur_arg] && strcmp(args[cur_arg], "show-uri") == 0) {
3974
0
      ctx->flags |= CLI_SHOWSESS_F_DUMP_URI;
3975
0
    }
3976
0
    else if (*args[cur_arg] && strcmp(args[cur_arg], "susp") == 0) {
3977
0
      ctx->flags |= CLI_SHOWSESS_F_SUSP;
3978
0
    }
3979
0
    else if (*args[cur_arg] && strcmp(args[cur_arg], "server") == 0) {
3980
0
      struct ist be_name, sv_name;
3981
0
      struct proxy *be;
3982
0
      struct server *sv;
3983
3984
0
      if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
3985
0
        return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
3986
3987
0
      if (!*args[cur_arg + 1])
3988
0
        return cli_err(appctx, "Missing server name (<backend>/<server>).\n");
3989
3990
0
      sv_name = ist(args[cur_arg + 1]);
3991
0
      be_name = istsplit(&sv_name, '/');
3992
0
      if (!istlen(sv_name))
3993
0
        return cli_err(appctx, "Require 'backend/server'.\n");
3994
3995
0
      if (!(be = proxy_be_by_name(ist0(be_name))))
3996
0
        return cli_err(appctx, "No such backend.\n");
3997
3998
0
      if (!(sv = server_find(be, ist0(sv_name))))
3999
0
        return cli_err(appctx, "No such server.\n");
4000
0
      ctx->flags |= CLI_SHOWSESS_F_SERVER;
4001
0
      ctx->filter = sv;
4002
0
      cur_arg++;
4003
0
    }
4004
0
    else if (*args[cur_arg] && strcmp(args[cur_arg], "backend") == 0) {
4005
0
      struct proxy *be;
4006
4007
0
      if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
4008
0
        return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
4009
4010
0
      if (!*args[cur_arg + 1])
4011
0
        return cli_err(appctx, "Missing backend name.\n");
4012
4013
0
      if (!(be = proxy_be_by_name(args[cur_arg + 1])))
4014
0
        return cli_err(appctx, "No such backend.\n");
4015
4016
0
      ctx->flags |= CLI_SHOWSESS_F_BACKEND;
4017
0
      ctx->filter = be;
4018
0
      cur_arg++;
4019
0
    }
4020
0
    else if (*args[cur_arg] && strcmp(args[cur_arg], "frontend") == 0) {
4021
0
      struct proxy *fe;
4022
4023
0
      if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
4024
0
        return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
4025
4026
0
      if (!*args[cur_arg + 1])
4027
0
        return cli_err(appctx, "Missing frontend name.\n");
4028
4029
0
      if (!(fe = proxy_fe_by_name(args[cur_arg + 1])))
4030
0
        return cli_err(appctx, "No such frontend.\n");
4031
4032
0
      ctx->flags |= CLI_SHOWSESS_F_FRONTEND;
4033
0
      ctx->filter = fe;
4034
0
      cur_arg++;
4035
0
    }
4036
0
    else {
4037
0
      chunk_printf(&trash, "Unsupported option '%s', try 'help' for more info.\n", args[cur_arg]);
4038
0
      return cli_err(appctx, trash.area);
4039
0
    }
4040
0
    cur_arg++;
4041
0
  }
4042
4043
  /* The back-ref must be reset, it will be detected and set by
4044
   * the dump code upon first invocation.
4045
   */
4046
0
  LIST_INIT(&ctx->bref.users);
4047
4048
  /* let's set our own stream's epoch to the current one and increment
4049
   * it so that we know which streams were already there before us.
4050
   */
4051
0
  appctx_strm(appctx)->stream_epoch = _HA_ATOMIC_FETCH_ADD(&stream_epoch, 1);
4052
0
  return 0;
4053
0
}
4054
4055
/* This function dumps all streams' states onto the stream connector's
4056
 * read buffer. It returns 0 if the output buffer is full and it needs
4057
 * to be called again, otherwise non-zero. It proceeds in an isolated
4058
 * thread so there is no thread safety issue here.
4059
 */
4060
static int cli_io_handler_dump_sess(struct appctx *appctx)
4061
0
{
4062
0
  struct show_sess_ctx *ctx = appctx->svcctx;
4063
0
  struct connection *conn;
4064
4065
0
  thread_isolate();
4066
4067
0
  if (ctx->thr >= global.nbthread) {
4068
    /* already terminated */
4069
0
    goto done;
4070
0
  }
4071
4072
0
  chunk_reset(&trash);
4073
4074
  /* first, let's detach the back-ref from a possible previous stream */
4075
0
  if (!LIST_ISEMPTY(&ctx->bref.users)) {
4076
0
    LIST_DELETE(&ctx->bref.users);
4077
0
    LIST_INIT(&ctx->bref.users);
4078
0
  } else if (!ctx->bref.ref) {
4079
    /* first call, start with first stream */
4080
0
    ctx->bref.ref = ha_thread_ctx[ctx->thr].streams.n;
4081
0
  }
4082
4083
  /* and start from where we stopped */
4084
0
  while (1) {
4085
0
    char pn[INET6_ADDRSTRLEN];
4086
0
    struct stream *curr_strm;
4087
0
    uint64_t request_ts;
4088
0
    int done= 0;
4089
4090
0
    if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].streams)
4091
0
      done = 1;
4092
0
    else {
4093
      /* check if we've found a stream created after issuing the "show sess" */
4094
0
      curr_strm = LIST_ELEM(ctx->bref.ref, struct stream *, list);
4095
0
      if ((int)(curr_strm->stream_epoch - appctx_strm(appctx)->stream_epoch) > 0)
4096
0
        done = 1;
4097
0
    }
4098
4099
0
    if (done) {
4100
0
      ctx->thr++;
4101
0
      if (ctx->thr >= global.nbthread)
4102
0
        break;
4103
0
      ctx->bref.ref = ha_thread_ctx[ctx->thr].streams.n;
4104
0
      continue;
4105
0
    }
4106
4107
0
    if (ctx->min_age) {
4108
0
      uint age = ns_to_sec(now_ns) - ns_to_sec(curr_strm->logs.request_ts);
4109
0
      if (age < ctx->min_age)
4110
0
        goto next_sess;
4111
0
    }
4112
4113
0
    if ((ctx->flags & CLI_SHOWSESS_F_SERVER) &&
4114
0
        (!(curr_strm->be->cap & PR_CAP_BE) || curr_strm->target != ctx->filter))
4115
0
      goto next_sess;
4116
4117
0
    if ((ctx->flags & CLI_SHOWSESS_F_BACKEND) && (curr_strm->be != ctx->filter))
4118
0
      goto next_sess;
4119
4120
0
    if ((ctx->flags & CLI_SHOWSESS_F_FRONTEND) && (curr_strm->sess->fe != ctx->filter))
4121
0
      goto next_sess;
4122
4123
0
    if (ctx->flags & CLI_SHOWSESS_F_SUSP) {
4124
      /* only show suspicious streams. Non-suspicious ones have a valid
4125
       * expiration date in the future and a valid front endpoint.
4126
       */
4127
0
      if (curr_strm->task->expire &&
4128
0
          !tick_is_expired(curr_strm->task->expire, now_ms) &&
4129
0
          curr_strm->scf && curr_strm->scf->sedesc && curr_strm->scf->sedesc->se)
4130
0
        goto next_sess;
4131
0
    }
4132
4133
0
    if (ctx->target) {
4134
0
      if (ctx->target != (void *)-1 && ctx->target != curr_strm)
4135
0
        goto next_sess;
4136
4137
0
      LIST_APPEND(&curr_strm->back_refs, &ctx->bref.users);
4138
      /* call the proper dump() function and return if we're missing space */
4139
0
      if (!stats_dump_full_strm_to_buffer(appctx, curr_strm))
4140
0
        goto full;
4141
4142
      /* stream dump complete */
4143
0
      LIST_DELETE(&ctx->bref.users);
4144
0
      LIST_INIT(&ctx->bref.users);
4145
0
      if (ctx->target != (void *)-1) {
4146
0
        ctx->target = NULL;
4147
0
        break;
4148
0
      }
4149
0
      else
4150
0
        goto next_sess;
4151
0
    }
4152
4153
0
    chunk_appendf(&trash,
4154
0
           "%p: proto=%s",
4155
0
           curr_strm,
4156
0
           strm_li(curr_strm) ? strm_li(curr_strm)->rx.proto->name : "?");
4157
4158
0
    conn = objt_conn(strm_orig(curr_strm));
4159
0
    switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
4160
0
    case AF_INET:
4161
0
    case AF_INET6:
4162
0
      chunk_appendf(&trash,
4163
0
             " src=%s:%d fe=%s be=%s srv=%s",
4164
0
             HA_ANON_CLI(pn),
4165
0
             get_host_port(conn->src),
4166
0
             HA_ANON_CLI(strm_fe(curr_strm)->id),
4167
0
             (curr_strm->be->cap & PR_CAP_BE) ? HA_ANON_CLI(curr_strm->be->id) : "<NONE>",
4168
0
             objt_server(curr_strm->target) ? HA_ANON_CLI(__objt_server(curr_strm->target)->id) : "<none>"
4169
0
             );
4170
0
      break;
4171
0
    case AF_UNIX:
4172
0
    case AF_CUST_ABNS:
4173
0
    case AF_CUST_ABNSZ:
4174
0
      chunk_appendf(&trash,
4175
0
             " src=unix:%d fe=%s be=%s srv=%s",
4176
0
             strm_li(curr_strm)->luid,
4177
0
             HA_ANON_CLI(strm_fe(curr_strm)->id),
4178
0
             (curr_strm->be->cap & PR_CAP_BE) ? HA_ANON_CLI(curr_strm->be->id) : "<NONE>",
4179
0
             objt_server(curr_strm->target) ? HA_ANON_CLI(__objt_server(curr_strm->target)->id) : "<none>"
4180
0
             );
4181
0
      break;
4182
0
    }
4183
4184
0
    request_ts = curr_strm->logs.accept_ts;
4185
0
    request_ts += ms_to_ns(curr_strm->logs.t_idle >= 0 ? curr_strm->logs.t_idle + curr_strm->logs.t_handshake : 0);
4186
0
    chunk_appendf(&trash,
4187
0
           " ts=%02x epoch=%#x age=%s calls=%u rate=%u cpu=%llu lat=%llu",
4188
0
                 curr_strm->task->state, curr_strm->stream_epoch,
4189
0
                 human_time(ns_to_sec(now_ns) - ns_to_sec(request_ts), 1),
4190
0
                 curr_strm->task->calls, read_freq_ctr(&curr_strm->call_rate),
4191
0
                 (unsigned long long)curr_strm->cpu_time, (unsigned long long)curr_strm->lat_time);
4192
4193
0
    chunk_appendf(&trash,
4194
0
           " rq[f=%06xh,i=%u,an=%02xh",
4195
0
           curr_strm->req.flags,
4196
0
                 (unsigned int)ci_data(&curr_strm->req),
4197
0
           curr_strm->req.analysers);
4198
4199
0
    chunk_appendf(&trash,
4200
0
           ",ax=%s]",
4201
0
           curr_strm->req.analyse_exp ?
4202
0
           human_time(TICKS_TO_MS(curr_strm->req.analyse_exp - now_ms),
4203
0
          TICKS_TO_MS(1000)) : "");
4204
4205
0
    chunk_appendf(&trash,
4206
0
           " rp[f=%06xh,i=%u,an=%02xh",
4207
0
           curr_strm->res.flags,
4208
0
                 (unsigned int)ci_data(&curr_strm->res),
4209
0
           curr_strm->res.analysers);
4210
0
    chunk_appendf(&trash,
4211
0
           ",ax=%s]",
4212
0
           curr_strm->res.analyse_exp ?
4213
0
           human_time(TICKS_TO_MS(curr_strm->res.analyse_exp - now_ms),
4214
0
          TICKS_TO_MS(1000)) : "");
4215
4216
0
    conn = sc_conn(curr_strm->scf);
4217
0
    chunk_appendf(&trash," scf=[%d,%1xh,fd=%d",
4218
0
            curr_strm->scf->state, curr_strm->scf->flags, conn_fd(conn));
4219
0
    chunk_appendf(&trash, ",rex=%s",
4220
0
            sc_ep_rcv_ex(curr_strm->scf) ?
4221
0
            human_time(TICKS_TO_MS(sc_ep_rcv_ex(curr_strm->scf) - now_ms),
4222
0
           TICKS_TO_MS(1000)) : "");
4223
0
    chunk_appendf(&trash,",wex=%s]",
4224
0
            sc_ep_snd_ex(curr_strm->scf) ?
4225
0
            human_time(TICKS_TO_MS(sc_ep_snd_ex(curr_strm->scf) - now_ms),
4226
0
           TICKS_TO_MS(1000)) : "");
4227
4228
0
    conn = sc_conn(curr_strm->scb);
4229
0
    chunk_appendf(&trash, " scb=[%d,%1xh,fd=%d",
4230
0
            curr_strm->scb->state, curr_strm->scb->flags, conn_fd(conn));
4231
0
    chunk_appendf(&trash, ",rex=%s",
4232
0
            sc_ep_rcv_ex(curr_strm->scb) ?
4233
0
            human_time(TICKS_TO_MS(sc_ep_rcv_ex(curr_strm->scb) - now_ms),
4234
0
           TICKS_TO_MS(1000)) : "");
4235
0
    chunk_appendf(&trash, ",wex=%s]",
4236
0
            sc_ep_snd_ex(curr_strm->scb) ?
4237
0
            human_time(TICKS_TO_MS(sc_ep_snd_ex(curr_strm->scb) - now_ms),
4238
0
           TICKS_TO_MS(1000)) : "");
4239
4240
0
    chunk_appendf(&trash,
4241
0
           " exp=%s rc=%d c_exp=%s",
4242
0
           curr_strm->task->expire ?
4243
0
           human_time(TICKS_TO_MS(curr_strm->task->expire - now_ms),
4244
0
          TICKS_TO_MS(1000)) : "",
4245
0
           curr_strm->conn_retries,
4246
0
           curr_strm->conn_exp ?
4247
0
           human_time(TICKS_TO_MS(curr_strm->conn_exp - now_ms),
4248
0
          TICKS_TO_MS(1000)) : "");
4249
0
    if (task_in_rq(curr_strm->task))
4250
0
      chunk_appendf(&trash, " run(nice=%d)", curr_strm->task->nice);
4251
4252
0
    if ((ctx->flags & CLI_SHOWSESS_F_DUMP_URI) &&
4253
0
        (curr_strm->flags & SF_TXN_MASK) == SF_TXN_HTTP &&
4254
0
        curr_strm->txn.http->uri)
4255
0
      chunk_appendf(&trash, " uri=\"%s\"",
4256
0
              HA_ANON_CLI(curr_strm->txn.http->uri));
4257
4258
0
    chunk_appendf(&trash, "\n");
4259
4260
0
    if (applet_putchk(appctx, &trash) == -1) {
4261
      /* let's try again later from this stream. We add ourselves into
4262
       * this stream's users so that it can remove us upon termination.
4263
       */
4264
0
      LIST_APPEND(&curr_strm->back_refs, &ctx->bref.users);
4265
0
      goto full;
4266
0
    }
4267
4268
0
  next_sess:
4269
0
    ctx->bref.ref = curr_strm->list.n;
4270
0
  }
4271
4272
0
  if (ctx->target && ctx->target != (void *)-1) {
4273
    /* specified stream not found */
4274
0
    if (ctx->section > 0)
4275
0
      chunk_appendf(&trash, "  *** session terminated while we were watching it ***\n");
4276
0
    else
4277
0
      chunk_appendf(&trash, "Session not found.\n");
4278
4279
0
    if (applet_putchk(appctx, &trash) == -1)
4280
0
      goto full;
4281
4282
0
    ctx->target = NULL;
4283
0
    ctx->uid = 0;
4284
0
    goto done;
4285
0
  }
4286
4287
0
 done:
4288
0
  thread_release();
4289
0
  return 1;
4290
0
 full:
4291
0
  thread_release();
4292
0
  return 0;
4293
0
}
4294
4295
static void cli_release_show_sess(struct appctx *appctx)
4296
0
{
4297
0
  struct show_sess_ctx *ctx = appctx->svcctx;
4298
4299
0
  if (ctx->thr < global.nbthread) {
4300
    /* a dump was aborted, either in error or timeout. We need to
4301
     * safely detach from the target stream's list. It's mandatory
4302
     * to lock because a stream on the target thread could be moving
4303
     * our node.
4304
     */
4305
0
    thread_isolate();
4306
0
    if (!LIST_ISEMPTY(&ctx->bref.users))
4307
0
      LIST_DELETE(&ctx->bref.users);
4308
0
    thread_release();
4309
0
  }
4310
0
}
4311
4312
/* Parses the "shutdown session" directive, it always returns 1 */
4313
static int cli_parse_shutdown_session(char **args, char *payload, struct appctx *appctx, void *private)
4314
0
{
4315
0
  struct stream *strm, *ptr;
4316
0
  int thr;
4317
4318
0
  if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
4319
0
    return 1;
4320
4321
0
  ptr = (void *)strtoul(args[2], NULL, 0);
4322
0
  if (!ptr)
4323
0
    return cli_err(appctx, "Session pointer expected (use 'show sess').\n");
4324
4325
0
  strm = NULL;
4326
4327
0
  thread_isolate();
4328
4329
  /* first, look for the requested stream in the stream table */
4330
0
  for (thr = 0; strm != ptr && thr < global.nbthread; thr++) {
4331
0
    list_for_each_entry(strm, &ha_thread_ctx[thr].streams, list) {
4332
0
      if (strm == ptr) {
4333
0
        stream_shutdown(strm, SF_ERR_KILLED);
4334
0
        break;
4335
0
      }
4336
0
    }
4337
0
  }
4338
4339
0
  thread_release();
4340
4341
  /* do we have the stream ? */
4342
0
  if (strm != ptr)
4343
0
    return cli_err(appctx, "No such session (use 'show sess').\n");
4344
4345
0
  return 1;
4346
0
}
4347
4348
/* Parses the "shutdown session server" directive, it always returns 1 */
4349
static int cli_parse_shutdown_sessions_server(char **args, char *payload, struct appctx *appctx, void *private)
4350
0
{
4351
0
  struct server *sv;
4352
4353
0
  if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
4354
0
    return 1;
4355
4356
0
  sv = cli_find_server(appctx, args[3]);
4357
0
  if (!sv)
4358
0
    return 1;
4359
4360
  /* kill all the stream that are on this server */
4361
0
  HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
4362
0
  srv_shutdown_streams(sv, SF_ERR_KILLED);
4363
0
  HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
4364
0
  return 1;
4365
0
}
4366
4367
/* register cli keywords */
4368
static struct cli_kw_list cli_kws = {{ },{
4369
  { { "show", "sess",  NULL },             "show sess [help|<id>|all] [opts...]     : report the list of current streams or dump this exact stream",   cli_parse_show_sess, cli_io_handler_dump_sess, cli_release_show_sess },
4370
  { { "shutdown", "session",  NULL },      "shutdown session [id]                   : kill a specific session",                                        cli_parse_shutdown_session, NULL, NULL },
4371
  { { "shutdown", "sessions",  "server" }, "shutdown sessions server <bk>/<srv>     : kill sessions on a server",                                      cli_parse_shutdown_sessions_server, NULL, NULL },
4372
  {{},}
4373
}};
4374
4375
INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
4376
4377
/* main configuration keyword registration. */
4378
static struct action_kw_list stream_tcp_req_keywords = { ILH, {
4379
  { "set-retries",   stream_parse_set_retries },
4380
  { "set-log-level", stream_parse_set_log_level },
4381
  { "set-nice",      stream_parse_set_nice },
4382
  { "switch-mode",   stream_parse_switch_mode },
4383
  { "use-service",   stream_parse_use_service },
4384
  { /* END */ }
4385
}};
4386
4387
INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &stream_tcp_req_keywords);
4388
4389
/* main configuration keyword registration. */
4390
static struct action_kw_list stream_tcp_res_keywords = { ILH, {
4391
  { "set-log-level", stream_parse_set_log_level },
4392
  { "set-nice",     stream_parse_set_nice },
4393
  { /* END */ }
4394
}};
4395
4396
INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &stream_tcp_res_keywords);
4397
4398
static struct action_kw_list stream_http_req_keywords = { ILH, {
4399
  { "set-retries",   stream_parse_set_retries },
4400
  { "set-log-level", stream_parse_set_log_level },
4401
  { "set-nice",      stream_parse_set_nice },
4402
  { "use-service",   stream_parse_use_service },
4403
  { /* END */ }
4404
}};
4405
4406
INITCALL1(STG_REGISTER, http_req_keywords_register, &stream_http_req_keywords);
4407
4408
static struct action_kw_list stream_http_res_keywords = { ILH, {
4409
  { "set-log-level", stream_parse_set_log_level },
4410
  { "set-nice",      stream_parse_set_nice },
4411
  { /* END */ }
4412
}};
4413
4414
INITCALL1(STG_REGISTER, http_res_keywords_register, &stream_http_res_keywords);
4415
4416
static struct action_kw_list stream_http_after_res_actions =  { ILH, {
4417
  { "set-log-level", stream_parse_set_log_level },
4418
  { /* END */ }
4419
}};
4420
4421
INITCALL1(STG_REGISTER, http_after_res_keywords_register, &stream_http_after_res_actions);
4422
4423
static int smp_fetch_cur_max_retries(const struct arg *args, struct sample *smp, const char *km, void *private)
4424
0
{
4425
0
  smp->flags = SMP_F_VOL_TXN;
4426
0
  smp->data.type = SMP_T_SINT;
4427
0
  if (!smp->strm)
4428
0
    return 0;
4429
4430
0
  smp->data.u.sint = smp->strm->max_retries;
4431
0
  return 1;
4432
0
}
4433
4434
static int smp_fetch_cur_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4435
0
{
4436
0
  smp->flags = SMP_F_VOL_TXN;
4437
0
  smp->data.type = SMP_T_SINT;
4438
0
  if (!smp->strm)
4439
0
    return 0;
4440
4441
0
  smp->data.u.sint = TICKS_TO_MS(smp->strm->connect_timeout);
4442
0
  return 1;
4443
0
}
4444
4445
static int smp_fetch_cur_client_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4446
0
{
4447
0
  smp->flags = SMP_F_VOL_TXN;
4448
0
  smp->data.type = SMP_T_SINT;
4449
0
  if (!smp->strm)
4450
0
    return 0;
4451
4452
0
  smp->data.u.sint = TICKS_TO_MS(smp->strm->scf->ioto);
4453
0
  return 1;
4454
0
}
4455
4456
static int smp_fetch_cur_server_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4457
0
{
4458
0
  smp->flags = SMP_F_VOL_TXN;
4459
0
  smp->data.type = SMP_T_SINT;
4460
0
  if (!smp->strm)
4461
0
    return 0;
4462
4463
0
  smp->data.u.sint = TICKS_TO_MS(smp->strm->scb->ioto);
4464
0
  return 1;
4465
0
}
4466
4467
static int smp_fetch_cur_queue_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4468
0
{
4469
0
  smp->flags = SMP_F_VOL_TXN;
4470
0
  smp->data.type = SMP_T_SINT;
4471
0
  if (!smp->strm)
4472
0
    return 0;
4473
4474
0
  smp->data.u.sint = TICKS_TO_MS(smp->strm->queue_timeout);
4475
0
  return 1;
4476
0
}
4477
4478
static int smp_fetch_cur_tarpit_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4479
0
{
4480
0
  smp->flags = SMP_F_VOL_TXN;
4481
0
  smp->data.type = SMP_T_SINT;
4482
0
  if (!smp->strm)
4483
0
    return 0;
4484
4485
0
  if (smp->strm->tarpit_timeout)
4486
0
    smp->data.u.sint = TICKS_TO_MS(smp->strm->tarpit_timeout);
4487
0
  else if (smp->strm->be)
4488
0
    smp->data.u.sint = TICKS_TO_MS(smp->strm->be->timeout.tarpit);
4489
0
  else
4490
0
    smp->data.u.sint = TICKS_TO_MS(smp->sess->fe->timeout.tarpit);
4491
4492
0
  return 1;
4493
0
}
4494
4495
static int smp_fetch_cur_tunnel_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
4496
0
{
4497
0
  smp->flags = SMP_F_VOL_TXN;
4498
0
  smp->data.type = SMP_T_SINT;
4499
0
  if (!smp->strm)
4500
0
    return 0;
4501
4502
0
  smp->data.u.sint = TICKS_TO_MS(smp->strm->tunnel_timeout);
4503
0
  return 1;
4504
0
}
4505
4506
static int smp_fetch_last_rule_file(const struct arg *args, struct sample *smp, const char *km, void *private)
4507
0
{
4508
0
  struct act_rule *rule;
4509
4510
0
  smp->flags = SMP_F_VOL_TXN;
4511
0
  smp->data.type = SMP_T_STR;
4512
0
  if (!smp->strm || smp->strm->last_entity.type != STRM_ENTITY_RULE)
4513
0
    return 0;
4514
4515
0
  rule = smp->strm->last_entity.ptr;
4516
0
  smp->flags |= SMP_F_CONST;
4517
0
  smp->data.u.str.area = (char *)rule->conf.file;
4518
0
  smp->data.u.str.data = strlen(rule->conf.file);
4519
0
  return 1;
4520
0
}
4521
4522
static int smp_fetch_last_rule_line(const struct arg *args, struct sample *smp, const char *km, void *private)
4523
0
{
4524
0
  struct act_rule *rule;
4525
4526
0
  smp->flags = SMP_F_VOL_TXN;
4527
0
  smp->data.type = SMP_T_SINT;
4528
0
  if (!smp->strm || smp->strm->last_entity.type != STRM_ENTITY_RULE)
4529
0
    return 0;
4530
4531
0
  rule = smp->strm->last_entity.ptr;
4532
0
  smp->data.u.sint = rule->conf.line;
4533
0
  return 1;
4534
0
}
4535
4536
static int smp_fetch_last_entity(const struct arg *args, struct sample *smp, const char *km, void *private)
4537
0
{
4538
0
  smp->flags = SMP_F_VOL_TXN;
4539
0
  smp->data.type = SMP_T_STR;
4540
0
  if (!smp->strm)
4541
0
    return 0;
4542
4543
0
  if (smp->strm->last_entity.type == STRM_ENTITY_RULE) {
4544
0
    struct act_rule *rule = smp->strm->last_entity.ptr;
4545
0
    struct buffer *trash = get_trash_chunk();
4546
4547
0
    trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line);
4548
0
    smp->data.u.str = *trash;
4549
0
  }
4550
0
  else if (smp->strm->last_entity.type == STRM_ENTITY_FILTER) {
4551
0
    struct filter *filter = smp->strm->last_entity.ptr;
4552
4553
0
    if (FLT_ID(filter)) {
4554
0
      smp->flags |= SMP_F_CONST;
4555
0
      smp->data.u.str.area = (char *)FLT_ID(filter);
4556
0
      smp->data.u.str.data = strlen(FLT_ID(filter));
4557
0
    }
4558
0
    else {
4559
0
      struct buffer *trash = get_trash_chunk();
4560
4561
0
      trash->data = snprintf(trash->area, trash->size, "%p", filter->config);
4562
0
      smp->data.u.str = *trash;
4563
0
    }
4564
0
  }
4565
0
  else
4566
0
    return 0;
4567
4568
0
  return 1;
4569
0
}
4570
4571
static int smp_fetch_waiting_entity(const struct arg *args, struct sample *smp, const char *km, void *private)
4572
0
{
4573
0
  smp->flags = SMP_F_VOL_TXN;
4574
0
  smp->data.type = SMP_T_STR;
4575
0
  if (!smp->strm)
4576
0
    return 0;
4577
4578
0
  if (smp->strm->waiting_entity.type == STRM_ENTITY_RULE) {
4579
0
    struct act_rule *rule = smp->strm->waiting_entity.ptr;
4580
0
    struct buffer *trash = get_trash_chunk();
4581
4582
0
    trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line);
4583
0
    smp->data.u.str = *trash;
4584
0
  }
4585
0
  else if (smp->strm->waiting_entity.type == STRM_ENTITY_FILTER) {
4586
0
    struct filter *filter = smp->strm->waiting_entity.ptr;
4587
4588
0
    if (FLT_ID(filter)) {
4589
0
      smp->flags |= SMP_F_CONST;
4590
0
      smp->data.u.str.area = (char *)FLT_ID(filter);
4591
0
      smp->data.u.str.data = strlen(FLT_ID(filter));
4592
0
    }
4593
0
    else {
4594
0
      struct buffer *trash = get_trash_chunk();
4595
4596
0
      trash->data = snprintf(trash->area, trash->size, "%p", filter->config);
4597
0
      smp->data.u.str = *trash;
4598
0
    }
4599
0
  }
4600
0
  else if (smp->strm->waiting_entity.type == STRM_ENTITY_WREQ_BODY) {
4601
0
    struct buffer *trash = get_trash_chunk();
4602
4603
0
    chunk_memcat(trash, "http-buffer-request", 19);
4604
0
    smp->data.u.str = *trash;
4605
0
  }
4606
0
  else
4607
0
    return 0;
4608
4609
0
  return 1;
4610
0
}
4611
4612
static int smp_fetch_sess_term_state(const struct arg *args, struct sample *smp, const char *km, void *private)
4613
0
{
4614
0
  struct buffer *trash = get_trash_chunk();
4615
4616
0
  smp->flags = SMP_F_VOLATILE;
4617
0
  smp->data.type = SMP_T_STR;
4618
0
  if (!smp->strm)
4619
0
    return 0;
4620
4621
0
  trash->area[trash->data++] = sess_term_cond[(smp->strm->flags & SF_ERR_MASK) >> SF_ERR_SHIFT];
4622
0
  trash->area[trash->data++] = sess_fin_state[(smp->strm->flags & SF_FINST_MASK) >> SF_FINST_SHIFT];
4623
4624
0
  smp->data.u.str = *trash;
4625
0
  smp->data.type = SMP_T_STR;
4626
0
  smp->flags &= ~SMP_F_CONST;
4627
0
  return 1;
4628
0
}
4629
4630
static int smp_fetch_conn_retries(const struct arg *args, struct sample *smp, const char *km, void *private)
4631
0
{
4632
0
  smp->flags = SMP_F_VOL_TXN;
4633
0
  smp->data.type = SMP_T_SINT;
4634
0
  if (!smp->strm)
4635
0
    return 0;
4636
4637
0
  if (!sc_state_in(smp->strm->scb->state, SC_SB_DIS|SC_SB_CLO))
4638
0
    smp->flags |= SMP_F_VOL_TEST;
4639
0
  smp->data.u.sint = smp->strm->conn_retries;
4640
0
  return 1;
4641
0
}
4642
4643
static int smp_fetch_tevts(const struct arg *args, struct sample *smp, const char *km, void *private)
4644
0
{
4645
0
  struct buffer *trash = get_trash_chunk();
4646
0
  struct connection *fconn, *bconn;
4647
0
  int fc_mux_ret, bc_mux_ret;
4648
4649
0
  fconn = smp->sess ? objt_conn(smp->sess->origin) : NULL;
4650
0
  bconn = smp->strm ? sc_conn(smp->strm->scb) : NULL;
4651
0
  fc_mux_ret = bc_mux_ret = -1;
4652
4653
0
  if (fconn && fconn->mux && fconn->mux->ctl)
4654
0
    fc_mux_ret = fconn->mux->ctl(fconn, MUX_CTL_TEVTS, NULL);
4655
0
  if (bconn && bconn->mux && bconn->mux->ctl)
4656
0
    bc_mux_ret = bconn->mux->ctl(bconn, MUX_CTL_TEVTS, NULL);
4657
4658
0
  chunk_printf(trash, "{%s,", tevt_evts2str(fconn ? fconn->term_evts_log : -1));
4659
0
  chunk_appendf(trash, "%s,", tevt_evts2str(fc_mux_ret));
4660
0
  chunk_appendf(trash, "%s,", tevt_evts2str(smp->strm ? smp->strm->scf->sedesc->term_evts_log : -1));
4661
0
  chunk_appendf(trash, "%s,", tevt_evts2str(smp->strm ? smp->strm->term_evts_log : -1));
4662
0
  chunk_appendf(trash, "%s,", tevt_evts2str(smp->strm ? smp->strm->scb->sedesc->term_evts_log : -1));
4663
0
  chunk_appendf(trash, "%s,", tevt_evts2str(bc_mux_ret));
4664
0
  chunk_appendf(trash, "%s}", tevt_evts2str(bconn ? bconn->term_evts_log : -1));
4665
4666
0
  smp->data.u.str = *trash;
4667
0
  smp->data.type = SMP_T_STR;
4668
0
  smp->flags = SMP_F_VOL_TEST | SMP_F_MAY_CHANGE;
4669
0
  return 1;
4670
0
}
4671
4672
static int smp_fetch_id32(const struct arg *args, struct sample *smp, const char *km, void *private)
4673
0
{
4674
0
  smp->flags = SMP_F_VOL_TXN;
4675
0
  smp->data.type = SMP_T_SINT;
4676
0
  if (!smp->strm)
4677
0
    return 0;
4678
0
  smp->data.u.sint = smp->strm->uniq_id;
4679
0
  return 1;
4680
0
}
4681
4682
static int smp_fetch_redispatched(const struct arg *args, struct sample *smp, const char *km, void *private)
4683
0
{
4684
0
  smp->flags = SMP_F_VOL_TXN;
4685
0
  smp->data.type = SMP_T_BOOL;
4686
0
  if (!smp->strm)
4687
0
    return 0;
4688
4689
0
  if (!sc_state_in(smp->strm->scb->state, SC_SB_DIS|SC_SB_CLO))
4690
0
    smp->flags |= SMP_F_VOL_TEST;
4691
0
  smp->data.u.sint = !!(smp->strm->flags & SF_REDISP);
4692
0
  return 1;
4693
0
}
4694
4695
/* Note: must not be declared <const> as its list will be overwritten.
4696
 * Please take care of keeping this list alphabetically sorted.
4697
 */
4698
static struct sample_fetch_kw_list smp_kws = {ILH, {
4699
  { "cur_connect_timeout",smp_fetch_cur_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
4700
  { "cur_client_timeout", smp_fetch_cur_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
4701
  { "cur_max_retries",    smp_fetch_cur_max_retries,    0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
4702
  { "cur_server_timeout", smp_fetch_cur_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
4703
  { "cur_queue_timeout",  smp_fetch_cur_queue_timeout,  0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
4704
  { "cur_tarpit_timeout", smp_fetch_cur_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND | SMP_USE_BKEND, },
4705
  { "cur_tunnel_timeout", smp_fetch_cur_tunnel_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
4706
  { "last_entity",        smp_fetch_last_entity,        0, NULL, SMP_T_STR,  SMP_USE_INTRN, },
4707
  { "last_rule_file",     smp_fetch_last_rule_file,     0, NULL, SMP_T_STR,  SMP_USE_INTRN, },
4708
  { "last_rule_line",     smp_fetch_last_rule_line,     0, NULL, SMP_T_SINT, SMP_USE_INTRN, },
4709
  { "term_events",        smp_fetch_tevts,              0, NULL, SMP_T_STR,  SMP_USE_INTRN, },
4710
  { "txn.conn_retries",   smp_fetch_conn_retries,       0, NULL, SMP_T_SINT, SMP_USE_L4SRV, },
4711
  { "txn.id32",           smp_fetch_id32,               0, NULL, SMP_T_SINT, SMP_USE_INTRN, },
4712
  { "txn.redispatched",   smp_fetch_redispatched,       0, NULL, SMP_T_BOOL, SMP_USE_L4SRV, },
4713
  { "txn.sess_term_state",smp_fetch_sess_term_state,    0, NULL, SMP_T_STR,  SMP_USE_INTRN, },
4714
  { "waiting_entity",     smp_fetch_waiting_entity,     0, NULL, SMP_T_STR,  SMP_USE_INTRN, },
4715
  { NULL, NULL, 0, 0, 0 },
4716
}};
4717
4718
INITCALL1(STG_REGISTER, sample_register_fetches, &smp_kws);
4719
4720
/*
4721
 * Local variables:
4722
 *  c-indent-level: 8
4723
 *  c-basic-offset: 8
4724
 * End:
4725
 */