/src/haproxy/src/stconn.c
Line | Count | Source |
1 | | /* |
2 | | * stream connector management functions |
3 | | * |
4 | | * Copyright 2021 Christopher Faulet <cfaulet@haproxy.com> |
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 <haproxy/api.h> |
14 | | #include <haproxy/applet.h> |
15 | | #include <haproxy/arg.h> |
16 | | #include <haproxy/connection.h> |
17 | | #include <haproxy/check.h> |
18 | | #include <haproxy/filters.h> |
19 | | #include <haproxy/hstream.h> |
20 | | #include <haproxy/http_ana.h> |
21 | | #include <haproxy/pipe.h> |
22 | | #include <haproxy/pool.h> |
23 | | #include <haproxy/proxy.h> |
24 | | #include <haproxy/sample.h> |
25 | | #include <haproxy/sc_strm.h> |
26 | | #include <haproxy/stconn.h> |
27 | | #include <haproxy/xref.h> |
28 | | |
29 | | DECLARE_TYPED_POOL(pool_head_connstream, "stconn", struct stconn); |
30 | | DECLARE_TYPED_POOL(pool_head_sedesc, "sedesc", struct sedesc); |
31 | | |
32 | | /* Only used by haload */ |
33 | | extern __attribute__((weak)) |
34 | | struct task *hld_strm_task(struct task *t, void *context, unsigned int state) |
35 | 0 | { |
36 | 0 | return NULL; |
37 | 0 | } |
38 | | |
39 | | static int sc_conn_recv(struct stconn *sc); |
40 | | static int sc_conn_send(struct stconn *sc); |
41 | | |
42 | | /* Initializes an endpoint */ |
43 | | void sedesc_init(struct sedesc *sedesc) |
44 | 0 | { |
45 | 0 | sedesc->se = NULL; |
46 | 0 | sedesc->conn = NULL; |
47 | 0 | sedesc->sc = NULL; |
48 | 0 | sedesc->lra = TICK_ETERNITY; |
49 | 0 | sedesc->fsb = TICK_ETERNITY; |
50 | 0 | sedesc->xref.peer = NULL; |
51 | 0 | se_fl_setall(sedesc, SE_FL_NONE); |
52 | 0 | sedesc->term_evts_log = 0; |
53 | 0 | sedesc->abort_info.info = 0; |
54 | 0 | sedesc->abort_info.code = 0; |
55 | |
|
56 | 0 | sedesc->iobuf.pipe = NULL; |
57 | 0 | sedesc->iobuf.buf = NULL; |
58 | 0 | sedesc->iobuf.offset = sedesc->iobuf.data = 0; |
59 | 0 | sedesc->iobuf.flags = IOBUF_FL_NONE; |
60 | |
|
61 | 0 | sedesc->kip = 0; |
62 | 0 | sedesc->kop = 0; |
63 | 0 | } |
64 | | |
65 | | /* Tries to alloc an endpoint and initialize it. Returns NULL on failure. */ |
66 | | struct sedesc *sedesc_new() |
67 | 0 | { |
68 | 0 | struct sedesc *sedesc; |
69 | |
|
70 | 0 | sedesc = pool_alloc(pool_head_sedesc); |
71 | 0 | if (unlikely(!sedesc)) |
72 | 0 | return NULL; |
73 | | |
74 | 0 | sedesc_init(sedesc); |
75 | 0 | return sedesc; |
76 | 0 | } |
77 | | |
78 | | /* Releases an endpoint. It is the caller responsibility to be sure it is safe |
79 | | * and it is not shared with another entity |
80 | | */ |
81 | | void sedesc_free(struct sedesc *sedesc) |
82 | 0 | { |
83 | 0 | if (sedesc) { |
84 | 0 | if (sedesc->iobuf.pipe) |
85 | 0 | put_pipe(sedesc->iobuf.pipe); |
86 | 0 | pool_free(pool_head_sedesc, sedesc); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | /* Performs a shutdown on the endpoint. This function deals with connection and |
91 | | * applet endpoints. It is responsible to set SE flags corresponding to the |
92 | | * given shut modes and to call right shutdown functions of the endpoint. It is |
93 | | * called from the sc_abort and sc_shutdown functions at the SC level. |
94 | | */ |
95 | | void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode) |
96 | 0 | { |
97 | 0 | struct sedesc *sdo; |
98 | 0 | struct se_abort_info *reason = NULL; |
99 | 0 | unsigned int flags = 0; |
100 | | |
101 | | /* Should never happen, placed here to be sure we forgot nothing */ |
102 | 0 | BUG_ON(!(mode & (SE_SHW_SILENT|SE_SHW_NORMAL))); |
103 | |
|
104 | 0 | if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(sedesc, SE_FL_SHW)) { |
105 | 0 | se_report_term_evt(sedesc, se_tevt_type_shutw); |
106 | 0 | flags |= (mode & SE_SHW_NORMAL) ? SE_FL_SHWN : SE_FL_SHWS; |
107 | 0 | } |
108 | 0 | if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(sedesc, SE_FL_SHR)) |
109 | 0 | flags |= (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR; |
110 | |
|
111 | 0 | if (se_fl_test(sedesc, SE_FL_T_MUX)) { |
112 | 0 | const struct mux_ops *mux = (sedesc->conn ? sedesc->conn->mux : NULL); |
113 | |
|
114 | 0 | if (flags) { |
115 | 0 | if (mux && mux->shut) { |
116 | 0 | sdo = se_opposite(sedesc); |
117 | 0 | if (sdo) |
118 | 0 | reason = &sdo->abort_info; |
119 | 0 | CALL_MUX_NO_RET(mux, shut(sedesc->sc, mode, reason)); |
120 | 0 | } |
121 | 0 | se_fl_set(sedesc, flags); |
122 | 0 | } |
123 | 0 | } |
124 | 0 | else if (se_fl_test(sedesc, SE_FL_T_APPLET)) { |
125 | 0 | struct appctx *appctx = sedesc->se; |
126 | |
|
127 | 0 | if (flags) { |
128 | 0 | if (appctx->applet->shut) { |
129 | 0 | sdo = se_opposite(sedesc); |
130 | 0 | if (sdo) |
131 | 0 | reason = &sdo->abort_info; |
132 | 0 | appctx->applet->shut(appctx, mode, reason); |
133 | 0 | } |
134 | 0 | se_fl_set(sedesc, flags); |
135 | 0 | } |
136 | |
|
137 | 0 | if (se_fl_test(sedesc, SE_FL_SHR) && se_fl_test(sedesc, SE_FL_SHW)) |
138 | 0 | appctx_shut(appctx); |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | /* Tries to allocate a new stconn and initialize its main fields. On |
143 | | * failure, nothing is allocated and NULL is returned. It is an internal |
144 | | * function. The caller must, at least, set the SE_FL_ORPHAN or SE_FL_DETACHED |
145 | | * flag. |
146 | | */ |
147 | | struct stconn *sc_new(struct sedesc *sedesc) |
148 | 0 | { |
149 | 0 | struct stconn *sc; |
150 | |
|
151 | 0 | sc = pool_alloc(pool_head_connstream); |
152 | |
|
153 | 0 | if (unlikely(!sc)) |
154 | 0 | goto alloc_error; |
155 | | |
156 | 0 | sc->obj_type = OBJ_TYPE_SC; |
157 | 0 | sc->flags = SC_FL_NONE; |
158 | 0 | sc->state = SC_ST_INI; |
159 | 0 | sc->ioto = TICK_ETERNITY; |
160 | 0 | sc->room_needed = 0; |
161 | 0 | sc->app = NULL; |
162 | 0 | sc->src = NULL; |
163 | 0 | sc->dst = NULL; |
164 | 0 | sc->bytes_in = sc->bytes_out = 0; |
165 | 0 | sc->wait_event.tasklet = NULL; |
166 | 0 | sc->wait_event.events = 0; |
167 | |
|
168 | 0 | sc->term_evts_log = 0; |
169 | | |
170 | | /* If there is no endpoint, allocate a new one now */ |
171 | 0 | if (!sedesc) { |
172 | 0 | sedesc = sedesc_new(); |
173 | 0 | if (unlikely(!sedesc)) |
174 | 0 | goto alloc_error; |
175 | 0 | } |
176 | 0 | sc->sedesc = sedesc; |
177 | 0 | sedesc->sc = sc; |
178 | |
|
179 | 0 | return sc; |
180 | | |
181 | 0 | alloc_error: |
182 | 0 | pool_free(pool_head_connstream, sc); |
183 | 0 | return NULL; |
184 | 0 | } |
185 | | |
186 | | /* Creates a new stream connector and its associated stream from a mux. <sd> must |
187 | | * be defined. It returns NULL on error. On success, the new stream connector is |
188 | | * returned. In this case, SE_FL_ORPHAN flag is removed. |
189 | | */ |
190 | | struct stconn *sc_new_from_endp(struct sedesc *sd, struct session *sess, struct buffer *input) |
191 | 0 | { |
192 | 0 | struct stconn *sc; |
193 | |
|
194 | 0 | sc = sc_new(sd); |
195 | 0 | if (unlikely(!sc)) |
196 | 0 | return NULL; |
197 | 0 | if (unlikely(!sess->fe->stream_new_from_sc(sess, sc, input))) { |
198 | 0 | sd->sc = NULL; |
199 | 0 | if (sc->sedesc != sd) { |
200 | | /* none was provided so sc_new() allocated one */ |
201 | 0 | sedesc_free(sc->sedesc); |
202 | 0 | } |
203 | 0 | pool_free(pool_head_connstream, sc); |
204 | 0 | se_fl_set(sd, SE_FL_ORPHAN); |
205 | 0 | return NULL; |
206 | 0 | } |
207 | 0 | se_fl_clr(sd, SE_FL_ORPHAN); |
208 | 0 | return sc; |
209 | 0 | } |
210 | | |
211 | | /* Creates a new stream connector from an stream. There is no endpoint here, thus it |
212 | | * will be created by sc_new(). So the SE_FL_DETACHED flag is set. It returns |
213 | | * NULL on error. On success, the new stream connector is returned. |
214 | | */ |
215 | | struct stconn *sc_new_from_strm(struct stream *strm, unsigned int flags) |
216 | 0 | { |
217 | 0 | struct stconn *sc; |
218 | |
|
219 | 0 | sc = sc_new(NULL); |
220 | 0 | if (unlikely(!sc)) |
221 | 0 | return NULL; |
222 | 0 | sc->flags |= flags; |
223 | |
|
224 | 0 | if (flags & SC_FL_ISBACK) |
225 | 0 | sc_ep_set(sc, SE_FL_APP_STARTED); |
226 | |
|
227 | 0 | sc_ep_set(sc, SE_FL_DETACHED); |
228 | 0 | sc->app = &strm->obj_type; |
229 | 0 | return sc; |
230 | 0 | } |
231 | | |
232 | | /* Creates a new stream connector from an health-check. There is no endpoint here, |
233 | | * thus it will be created by sc_new(). So the SE_FL_DETACHED flag is set. It |
234 | | * returns NULL on error. On success, the new stream connector is returned. |
235 | | */ |
236 | | struct stconn *sc_new_from_check(struct check *check) |
237 | 0 | { |
238 | 0 | struct stconn *sc; |
239 | |
|
240 | 0 | sc = sc_new(NULL); |
241 | 0 | if (unlikely(!sc)) |
242 | 0 | return NULL; |
243 | 0 | sc->flags = SC_FL_ISBACK; |
244 | 0 | sc_ep_set(sc, SE_FL_APP_STARTED); |
245 | 0 | sc_ep_set(sc, SE_FL_DETACHED); |
246 | 0 | sc->app = &check->obj_type; |
247 | 0 | return sc; |
248 | 0 | } |
249 | | |
250 | | /* Releases a stconn previously allocated by sc_new(), as well as its |
251 | | * endpoint, if it exists. This function is called internally or on error path. |
252 | | */ |
253 | | void sc_free(struct stconn *sc) |
254 | 0 | { |
255 | 0 | sockaddr_free(&sc->src); |
256 | 0 | sockaddr_free(&sc->dst); |
257 | 0 | if (sc->sedesc) { |
258 | 0 | BUG_ON(!sc_ep_test(sc, SE_FL_DETACHED)); |
259 | 0 | sedesc_free(sc->sedesc); |
260 | 0 | } |
261 | 0 | tasklet_free(sc->wait_event.tasklet); |
262 | 0 | pool_free(pool_head_connstream, sc); |
263 | 0 | } |
264 | | |
265 | | /* Conditionally removes a stream connector if it is detached and if there is no app |
266 | | * layer defined. Except on error path, this one must be used. if release, the |
267 | | * pointer on the SC is set to NULL. |
268 | | */ |
269 | | static void sc_free_cond(struct stconn **scp) |
270 | 0 | { |
271 | 0 | struct stconn *sc = *scp; |
272 | |
|
273 | 0 | if (!sc->app && (!sc->sedesc || sc_ep_test(sc, SE_FL_DETACHED))) { |
274 | 0 | sc_free(sc); |
275 | 0 | *scp = NULL; |
276 | 0 | } |
277 | 0 | } |
278 | | |
279 | | |
280 | | /* Attaches a stconn to a mux endpoint and sets the endpoint ctx. Returns |
281 | | * -1 on error and 0 on success. SE_FL_DETACHED flag is removed. This function is |
282 | | * called from a mux when it is attached to a stream or a health-check. |
283 | | */ |
284 | | int sc_attach_mux(struct stconn *sc, void *sd, void *ctx) |
285 | 0 | { |
286 | 0 | struct connection *conn = ctx; |
287 | 0 | struct sedesc *sedesc = sc->sedesc; |
288 | |
|
289 | 0 | if (sc_strm(sc)) { |
290 | 0 | if (!sc->wait_event.tasklet) { |
291 | 0 | sc->wait_event.tasklet = tasklet_new(); |
292 | 0 | if (!sc->wait_event.tasklet) |
293 | 0 | return -1; |
294 | 0 | sc->wait_event.tasklet->process = sc_conn_io_cb; |
295 | 0 | sc->wait_event.tasklet->context = sc; |
296 | 0 | sc->wait_event.events = 0; |
297 | 0 | } |
298 | | |
299 | 0 | xref_create(&sc->sedesc->xref, &sc_opposite(sc)->sedesc->xref); |
300 | 0 | } |
301 | 0 | else if (sc_check(sc)) { |
302 | 0 | if (!sc->wait_event.tasklet) { |
303 | 0 | sc->wait_event.tasklet = tasklet_new(); |
304 | 0 | if (!sc->wait_event.tasklet) |
305 | 0 | return -1; |
306 | 0 | sc->wait_event.tasklet->process = srv_chk_io_cb; |
307 | 0 | sc->wait_event.tasklet->context = sc; |
308 | 0 | sc->wait_event.events = 0; |
309 | 0 | } |
310 | 0 | } |
311 | 0 | else if (sc_hldstream(sc)) { |
312 | 0 | if (!sc->wait_event.tasklet) { |
313 | 0 | sc->wait_event.tasklet = tasklet_new(); |
314 | 0 | if (!sc->wait_event.tasklet) |
315 | 0 | return -1; |
316 | 0 | sc->wait_event.tasklet->process = hld_strm_task; |
317 | 0 | sc->wait_event.tasklet->expire = TICK_ETERNITY; |
318 | 0 | sc->wait_event.tasklet->context = __sc_hldstream(sc);; |
319 | 0 | sc->wait_event.events = 0; |
320 | 0 | } |
321 | 0 | } |
322 | | |
323 | 0 | sedesc->se = sd; |
324 | 0 | sedesc->conn = ctx; |
325 | 0 | se_fl_set(sedesc, SE_FL_T_MUX); |
326 | 0 | se_fl_clr(sedesc, SE_FL_DETACHED); |
327 | 0 | if (!conn->ctx) |
328 | 0 | conn->ctx = sc; |
329 | 0 | return 0; |
330 | 0 | } |
331 | | |
332 | | /* Attaches a stconn to an applet endpoint and sets the endpoint |
333 | | * ctx. Returns -1 on error and 0 on success. SE_FL_DETACHED flag is |
334 | | * removed. This function is called by a stream when a backend applet is |
335 | | * registered. |
336 | | */ |
337 | | static int sc_attach_applet(struct stconn *sc, struct appctx *appctx) |
338 | 0 | { |
339 | 0 | sc->sedesc->se = appctx; |
340 | 0 | sc_ep_set(sc, SE_FL_T_APPLET); |
341 | 0 | sc_ep_clr(sc, SE_FL_DETACHED); |
342 | 0 | if (sc_strm(sc)) |
343 | 0 | xref_create(&sc->sedesc->xref, &sc_opposite(sc)->sedesc->xref); |
344 | |
|
345 | 0 | return 0; |
346 | 0 | } |
347 | | |
348 | | /* Attaches a stconn to a app layer and sets the relevant |
349 | | * callbacks. Returns -1 on error and 0 on success. SE_FL_ORPHAN flag is |
350 | | * removed. This function is called by a stream when it is created to attach it |
351 | | * on the stream connector on the client side. |
352 | | */ |
353 | | int sc_attach_strm(struct stconn *sc, struct stream *strm) |
354 | 0 | { |
355 | 0 | sc->app = &strm->obj_type; |
356 | 0 | sc_ep_clr(sc, SE_FL_ORPHAN); |
357 | 0 | sc_ep_report_read_activity(sc); |
358 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX)) { |
359 | 0 | sc->wait_event.tasklet = tasklet_new(); |
360 | 0 | if (!sc->wait_event.tasklet) |
361 | 0 | return -1; |
362 | 0 | sc->wait_event.tasklet->process = sc_conn_io_cb; |
363 | 0 | sc->wait_event.tasklet->context = sc; |
364 | 0 | sc->wait_event.events = 0; |
365 | 0 | } |
366 | 0 | return 0; |
367 | 0 | } |
368 | | |
369 | | /* Attach a stconn to a haterm layer and sets the relevant |
370 | | * callbacks. Returns -1 on error and 0 on success. SE_FL_ORPHAN flag is |
371 | | * removed. This function is called by a haterm stream when it is created |
372 | | * to attach it on the stream connector on the client side. |
373 | | */ |
374 | | int sc_attach_hstream(struct stconn *sc, struct hstream *hs) |
375 | 0 | { |
376 | 0 | BUG_ON(!sc_ep_test(sc, SE_FL_T_MUX)); |
377 | |
|
378 | 0 | sc->app = &hs->obj_type; |
379 | 0 | sc_ep_clr(sc, SE_FL_ORPHAN); |
380 | 0 | sc_ep_report_read_activity(sc); |
381 | 0 | sc->wait_event.tasklet = tasklet_new(); |
382 | 0 | if (!sc->wait_event.tasklet) |
383 | 0 | return -1; |
384 | | |
385 | 0 | sc->wait_event.tasklet->process = sc_hstream_io_cb; |
386 | 0 | sc->wait_event.tasklet->context = sc; |
387 | 0 | sc->wait_event.events = 0; |
388 | 0 | return 0; |
389 | 0 | } |
390 | | |
391 | | /* Detaches the stconn from the endpoint, if any. For a connecrion, if a |
392 | | * mux owns the connection ->detach() callback is called. Otherwise, it means |
393 | | * the stream connector owns the connection. In this case the connection is closed |
394 | | * and released. For an applet, the appctx is released. If still allocated, the |
395 | | * endpoint is reset and flag as detached. If the app layer is also detached, |
396 | | * the stream connector is released. |
397 | | */ |
398 | | static void sc_detach_endp(struct stconn **scp) |
399 | 0 | { |
400 | 0 | struct stconn *sc = *scp; |
401 | 0 | struct xref *peer; |
402 | |
|
403 | 0 | if (!sc) |
404 | 0 | return; |
405 | | |
406 | | |
407 | | /* Remove my link in the original objects. */ |
408 | 0 | peer = xref_get_peer_and_lock(&sc->sedesc->xref); |
409 | 0 | if (peer) |
410 | 0 | xref_disconnect(&sc->sedesc->xref, peer); |
411 | |
|
412 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX)) { |
413 | 0 | struct connection *conn = __sc_conn(sc); |
414 | 0 | struct sedesc *sedesc = sc->sedesc; |
415 | |
|
416 | 0 | if (conn->mux) { |
417 | 0 | if (sc->wait_event.events != 0) |
418 | 0 | conn->mux->unsubscribe(sc, sc->wait_event.events, &sc->wait_event); |
419 | 0 | se_fl_set(sedesc, SE_FL_ORPHAN); |
420 | 0 | sedesc->sc = NULL; |
421 | 0 | sc->sedesc = NULL; |
422 | 0 | CALL_MUX_NO_RET(conn->mux, detach(sedesc)); |
423 | 0 | } |
424 | 0 | else { |
425 | | /* It's too early to have a mux, let's just destroy |
426 | | * the connection |
427 | | */ |
428 | 0 | conn_stop_tracking(conn); |
429 | 0 | conn_full_close(conn); |
430 | 0 | if (conn->destroy_cb) |
431 | 0 | conn->destroy_cb(conn); |
432 | 0 | conn_free(conn); |
433 | 0 | } |
434 | 0 | } |
435 | 0 | else if (sc_ep_test(sc, SE_FL_T_APPLET)) { |
436 | 0 | struct appctx *appctx = __sc_appctx(sc); |
437 | |
|
438 | 0 | sc_ep_set(sc, SE_FL_ORPHAN); |
439 | 0 | sc->sedesc->sc = NULL; |
440 | 0 | sc->sedesc = NULL; |
441 | 0 | se_shutdown(appctx->sedesc, SE_SHR_RESET|SE_SHW_NORMAL); |
442 | 0 | appctx_free(appctx); |
443 | 0 | } |
444 | |
|
445 | 0 | if (sc->sedesc) { |
446 | | /* the SD wasn't used and can be recycled */ |
447 | 0 | sc->sedesc->se = NULL; |
448 | 0 | sc->sedesc->conn = NULL; |
449 | 0 | sc->sedesc->flags = 0; |
450 | 0 | sc_ep_set(sc, SE_FL_DETACHED); |
451 | 0 | } |
452 | | |
453 | | /* FIXME: Rest SC for now but must be reviewed. SC flags are only |
454 | | * connection related for now but this will evolved |
455 | | */ |
456 | 0 | sc->flags &= SC_FL_ISBACK; |
457 | 0 | sc_free_cond(scp); |
458 | 0 | } |
459 | | |
460 | | /* Detaches the stconn from the app layer. If there is no endpoint attached |
461 | | * to the stconn |
462 | | */ |
463 | | static void sc_detach_app(struct stconn **scp) |
464 | 0 | { |
465 | 0 | struct stconn *sc = *scp; |
466 | |
|
467 | 0 | if (!sc) |
468 | 0 | return; |
469 | | |
470 | 0 | sc->app = NULL; |
471 | 0 | sockaddr_free(&sc->src); |
472 | 0 | sockaddr_free(&sc->dst); |
473 | |
|
474 | 0 | tasklet_free(sc->wait_event.tasklet); |
475 | 0 | sc->wait_event.tasklet = NULL; |
476 | 0 | sc->wait_event.events = 0; |
477 | 0 | sc_free_cond(scp); |
478 | 0 | } |
479 | | |
480 | | /* Destroy the stconn. It is detached from its endpoint and its |
481 | | * application. After this call, the stconn must be considered as released. |
482 | | */ |
483 | | void sc_destroy(struct stconn *sc) |
484 | 0 | { |
485 | 0 | sc_detach_endp(&sc); |
486 | 0 | sc_detach_app(&sc); |
487 | 0 | BUG_ON_HOT(sc); |
488 | 0 | } |
489 | | |
490 | | /* Resets the stream connector endpoint. It happens when the app layer want to renew |
491 | | * its endpoint. For a connection retry for instance. If a mux or an applet is |
492 | | * attached, a new endpoint is created. Returns -1 on error and 0 on success. |
493 | | */ |
494 | | int sc_reset_endp(struct stconn *sc) |
495 | 0 | { |
496 | 0 | struct sedesc *new_sd; |
497 | |
|
498 | 0 | BUG_ON(!sc->app); |
499 | |
|
500 | 0 | if (!__sc_endp(sc)) { |
501 | | /* endpoint not attached or attached to a mux with no |
502 | | * target. Thus the endpoint will not be release but just |
503 | | * reset. The app is still attached, the sc will not be |
504 | | * released. |
505 | | */ |
506 | 0 | sc_detach_endp(&sc); |
507 | 0 | return 0; |
508 | 0 | } |
509 | | |
510 | | /* allocate the new endpoint first to be able to set error if it |
511 | | * fails */ |
512 | 0 | new_sd = sedesc_new(); |
513 | 0 | if (!unlikely(new_sd)) |
514 | 0 | return -1; |
515 | | |
516 | | /* The app is still attached, the sc will not be released */ |
517 | 0 | sc_detach_endp(&sc); |
518 | 0 | BUG_ON(!sc); |
519 | 0 | BUG_ON(sc->sedesc); |
520 | 0 | sc->sedesc = new_sd; |
521 | 0 | sc->sedesc->sc = sc; |
522 | 0 | sc->bytes_in = sc->bytes_out = 0; |
523 | 0 | sc_ep_set(sc, SE_FL_DETACHED); |
524 | 0 | return 0; |
525 | 0 | } |
526 | | |
527 | | |
528 | | /* Create an applet to handle a stream connector as a new appctx. The SC will |
529 | | * wake it up every time it is solicited. The appctx must be deleted by the task |
530 | | * handler using sc_detach_endp(), possibly from within the function itself. |
531 | | * It also pre-initializes the applet's context and returns it (or NULL in case |
532 | | * it could not be allocated). |
533 | | */ |
534 | | struct appctx *sc_applet_create(struct stconn *sc, struct applet *app) |
535 | 0 | { |
536 | 0 | struct appctx *appctx; |
537 | |
|
538 | 0 | appctx = appctx_new_here(app, sc->sedesc); |
539 | 0 | if (!appctx) |
540 | 0 | return NULL; |
541 | 0 | if (sc_attach_applet(sc, appctx) == -1) { |
542 | 0 | appctx_free_on_early_error(appctx); |
543 | 0 | return NULL; |
544 | 0 | } |
545 | 0 | appctx->t->nice = __sc_strm(sc)->task->nice; |
546 | 0 | applet_need_more_data(appctx); |
547 | 0 | appctx_wakeup(appctx); |
548 | |
|
549 | 0 | sc->state = SC_ST_RDY; |
550 | 0 | return appctx; |
551 | 0 | } |
552 | | |
553 | | /* Conditionally forward the close to the write side. It return 1 if it can be |
554 | | * forwarded. It is the caller responsibility to forward the close to the write |
555 | | * side. Otherwise, 0 is returned. In this case, SC_FL_SHUT_WANTED flag may be set on |
556 | | * the consumer SC if we are only waiting for the outgoing data to be flushed. |
557 | | */ |
558 | | static inline int sc_cond_forward_shut(struct stconn *sc) |
559 | 0 | { |
560 | | /* The close must not be forwarded */ |
561 | 0 | if (!(sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) || !(sc->flags & SC_FL_NOHALF)) |
562 | 0 | return 0; |
563 | | |
564 | 0 | if ((co_data(sc_ic(sc)) || sc_ep_have_ff_data(sc_opposite(sc))) && !(sc_ic(sc)->flags & CF_WRITE_TIMEOUT)) { |
565 | | /* the shutdown cannot be forwarded now because |
566 | | * we should flush outgoing data first. But instruct the output |
567 | | * channel it should be done ASAP. |
568 | | */ |
569 | 0 | sc_schedule_shutdown(sc); |
570 | 0 | return 0; |
571 | 0 | } |
572 | | |
573 | | /* the close can be immediately forwarded to the write side */ |
574 | 0 | return 1; |
575 | 0 | } |
576 | | |
577 | | |
578 | | static inline int sc_is_fastfwd_supported(struct stconn *sc) |
579 | 0 | { |
580 | 0 | return (!(global.tune.no_zero_copy_fwd & NO_ZERO_COPY_FWD) && |
581 | 0 | !(sc->flags & SC_FL_NO_FASTFWD) && |
582 | 0 | sc_ep_test(sc, SE_FL_MAY_FASTFWD_PROD) && |
583 | 0 | sc_ep_test(sc_opposite(sc), SE_FL_MAY_FASTFWD_CONS) && |
584 | 0 | sc_ic(sc)->to_forward); |
585 | 0 | } |
586 | | |
587 | | /* |
588 | | * This function performs a shutdown-read on a detached stream connector in a |
589 | | * connected or init state (it does nothing for other states). It either shuts |
590 | | * the read side or marks itself as closed. The buffer flags are updated to |
591 | | * reflect the new state. If the stream connector has SC_FL_NOHALF, we also |
592 | | * forward the close to the write side. The owner task is woken up if it exists. |
593 | | */ |
594 | | void sc_abort(struct stconn *sc) |
595 | 0 | { |
596 | 0 | struct channel *ic = sc_ic(sc); |
597 | |
|
598 | 0 | BUG_ON(!sc_strm(sc)); |
599 | |
|
600 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
601 | 0 | return; |
602 | | |
603 | 0 | sc->flags |= SC_FL_ABRT_DONE; |
604 | 0 | ic->flags |= CF_READ_EVENT; |
605 | |
|
606 | 0 | if (!sc_state_in(sc->state, SC_SB_CON|SC_SB_RDY|SC_SB_EST)) |
607 | 0 | return; |
608 | | |
609 | 0 | if (sc->flags & SC_FL_SHUT_DONE) { |
610 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)) |
611 | 0 | se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT); |
612 | |
|
613 | 0 | sc->state = SC_ST_DIS; |
614 | 0 | if (sc->flags & SC_FL_ISBACK) |
615 | 0 | __sc_strm(sc)->conn_exp = TICK_ETERNITY; |
616 | 0 | } |
617 | 0 | else if (sc_cond_forward_shut(sc)) |
618 | 0 | return sc_shutdown(sc); |
619 | | |
620 | 0 | if (!sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)) { |
621 | | /* note that if the task exists, it must unregister itself once it runs */ |
622 | 0 | if (!(sc->flags & SC_FL_DONT_WAKE)) |
623 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO); |
624 | 0 | } |
625 | 0 | } |
626 | | |
627 | | /* |
628 | | * This function performs a shutdown-write on a detached stream connector in a |
629 | | * connected or init state (it does nothing for other states). It either shuts |
630 | | * the write side or marks itself as closed. The buffer flags are updated to |
631 | | * reflect the new state. It does also close everything if the SC was marked as |
632 | | * being in error state. The owner task is woken up if it exists. |
633 | | */ |
634 | | void sc_shutdown(struct stconn *sc) |
635 | 0 | { |
636 | |
|
637 | 0 | struct channel *ic = sc_ic(sc); |
638 | 0 | struct channel *oc = sc_oc(sc); |
639 | |
|
640 | 0 | BUG_ON(!sc_strm(sc)); |
641 | |
|
642 | 0 | sc->flags &= ~SC_FL_SHUT_WANTED; |
643 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
644 | 0 | return; |
645 | 0 | sc->flags |= SC_FL_SHUT_DONE; |
646 | 0 | oc->flags |= CF_WRITE_EVENT; |
647 | 0 | sc_set_hcto(sc); |
648 | 0 | sc_report_term_evt(sc, strm_tevt_type_shutw); |
649 | |
|
650 | 0 | if (sc_ep_test(sc, SE_FL_T_APPLET)) { |
651 | | /* on shutw we always wake the applet up */ |
652 | 0 | appctx_wakeup(__sc_appctx(sc)); |
653 | 0 | } |
654 | |
|
655 | 0 | switch (sc->state) { |
656 | 0 | case SC_ST_RDY: |
657 | 0 | case SC_ST_EST: |
658 | | /* we have to shut before closing, otherwise some short messages |
659 | | * may never leave the system, especially when there are remaining |
660 | | * unread data in the socket input buffer, or when nolinger is set. |
661 | | * However, if SC_FL_NOLINGER is explicitly set, we know there is |
662 | | * no risk so we close both sides immediately. |
663 | | */ |
664 | 0 | if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_EOS|SC_FL_ABRT_DONE)) && |
665 | 0 | !(ic->flags & CF_DONT_READ)) { |
666 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)) |
667 | 0 | se_shutdown(sc->sedesc, SE_SHW_NORMAL); |
668 | 0 | return; |
669 | 0 | } |
670 | | |
671 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)) |
672 | 0 | se_shutdown(sc->sedesc, SE_SHR_RESET|((sc->flags & SC_FL_NOLINGER) ? SE_SHW_SILENT : SE_SHW_NORMAL)); |
673 | |
|
674 | 0 | sc->state = SC_ST_DIS; |
675 | 0 | break; |
676 | | |
677 | 0 | case SC_ST_CON: |
678 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX)) { |
679 | | /* we may have to close a pending connection, and mark the |
680 | | * response buffer as abort |
681 | | */ |
682 | 0 | se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT); |
683 | 0 | } |
684 | 0 | __fallthrough; |
685 | 0 | case SC_ST_CER: |
686 | 0 | case SC_ST_QUE: |
687 | 0 | case SC_ST_TAR: |
688 | | /* Note that none of these states may happen with applets */ |
689 | 0 | sc->state = SC_ST_DIS; |
690 | 0 | break; |
691 | 0 | default: |
692 | 0 | break; |
693 | 0 | } |
694 | | |
695 | 0 | sc->flags &= ~SC_FL_NOLINGER; |
696 | 0 | if (!(sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE))) |
697 | 0 | sc->flags |= SC_FL_ABRT_DONE; |
698 | 0 | if (sc->flags & SC_FL_ISBACK) |
699 | 0 | __sc_strm(sc)->conn_exp = TICK_ETERNITY; |
700 | |
|
701 | 0 | if (!sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)) { |
702 | | /* note that if the task exists, it must unregister itself once it runs */ |
703 | 0 | if (!(sc->flags & SC_FL_DONT_WAKE)) |
704 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO); |
705 | 0 | } |
706 | 0 | } |
707 | | |
708 | | /* This is to be used after making some room available in a channel. It will |
709 | | * return without doing anything if the stream connector's RX path is blocked. |
710 | | * It will automatically mark the stream connector as busy processing the end |
711 | | * point in order to avoid useless repeated wakeups. |
712 | | * It will then woken the right entity to enable receipt of new data. |
713 | | */ |
714 | | void sc_chk_rcv(struct stconn *sc) |
715 | 0 | { |
716 | 0 | BUG_ON(!sc_strm(sc)); |
717 | |
|
718 | 0 | if (sc_ep_test(sc, SE_FL_APPLET_NEED_CONN) && |
719 | 0 | sc_state_in(sc_opposite(sc)->state, SC_SB_RDY|SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) { |
720 | | /* connection available (or closed), so wake applet up to handle |
721 | | * the event. here we are not in the applet context (but most |
722 | | * probably in the connection context). |
723 | | */ |
724 | 0 | appctx_wakeup(__sc_appctx(sc)); |
725 | 0 | } |
726 | |
|
727 | 0 | if (!sc_is_recv_allowed(sc)) |
728 | 0 | return; |
729 | | |
730 | 0 | if (!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST)) |
731 | 0 | return; |
732 | | |
733 | 0 | sc_ep_set(sc, SE_FL_HAVE_NO_DATA); |
734 | | |
735 | | /* (re)start reading */ |
736 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX)) { |
737 | 0 | if (sc_state_in(sc->state, SC_SB_CON|SC_SB_RDY|SC_SB_EST)) |
738 | 0 | tasklet_wakeup(sc->wait_event.tasklet, TASK_WOKEN_IO); |
739 | 0 | } |
740 | 0 | else if (sc_ep_test(sc, SE_FL_T_APPLET)) { |
741 | 0 | if (!sc_ep_have_ff_data(sc_opposite(sc))) |
742 | 0 | appctx_wakeup(__sc_appctx(sc)); |
743 | 0 | } |
744 | 0 | else { |
745 | | /* In theory, it should not happen. This CHECK_IF will be used to validate it (or not...) */ |
746 | 0 | CHECK_IF(!sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)); |
747 | 0 | if (!(sc->flags & SC_FL_DONT_WAKE)) |
748 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO); |
749 | 0 | } |
750 | 0 | } |
751 | | |
752 | | |
753 | | /* This function is used for inter-stream connector calls. It is called by the |
754 | | * producer to inform the consumer side that it may be interested in checking |
755 | | * for data in the buffer. Note that it intentionally does not update timeouts, |
756 | | * so that we can still check them later at wake-up. |
757 | | */ |
758 | | static inline void sc_chk_snd(struct stconn *sc) |
759 | 0 | { |
760 | 0 | struct channel *oc = sc_oc(sc); |
761 | |
|
762 | 0 | BUG_ON(!sc_strm(sc)); |
763 | |
|
764 | 0 | if (sc_ep_test(sc, SE_FL_T_MUX)) { |
765 | 0 | if (unlikely(!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST) || |
766 | 0 | (sc->flags & SC_FL_SHUT_DONE))) |
767 | 0 | return; |
768 | | |
769 | 0 | if (unlikely(!co_data(oc) && !sc_ep_have_ff_data(sc))) /* called with nothing to send ! */ |
770 | 0 | return; |
771 | | |
772 | 0 | if (!sc_ep_have_ff_data(sc) && /* data wants to be fast-forwarded ASAP */ |
773 | 0 | !sc_ep_test(sc, SE_FL_WAIT_DATA)) /* not waiting for data */ |
774 | 0 | return; |
775 | | |
776 | 0 | if (!(sc->wait_event.events & SUB_RETRY_SEND)) |
777 | 0 | sc_conn_send(sc); |
778 | |
|
779 | 0 | if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING) || sc_is_conn_error(sc)) { |
780 | | /* Write error on the file descriptor */ |
781 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); |
782 | 0 | goto out_wakeup; |
783 | 0 | } |
784 | | |
785 | | /* OK, so now we know that some data might have been sent, and that we may |
786 | | * have to poll first. We have to do that too if the buffer is not empty. |
787 | | */ |
788 | 0 | if (!co_data(oc) && !sc_ep_have_ff_data(sc)) { |
789 | | /* the connection is established but we can't write. Either the |
790 | | * buffer is empty, or we just refrain from sending because the |
791 | | * ->o limit was reached. Maybe we just wrote the last |
792 | | * chunk and need to close. |
793 | | */ |
794 | 0 | if ((oc->flags & CF_AUTO_CLOSE) && |
795 | 0 | ((sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED) && |
796 | 0 | sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST)) { |
797 | 0 | sc_shutdown(sc); |
798 | 0 | goto out_wakeup; |
799 | 0 | } |
800 | | |
801 | 0 | if ((sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == 0) |
802 | 0 | sc_ep_set(sc, SE_FL_WAIT_DATA); |
803 | 0 | } |
804 | 0 | else { |
805 | | /* Otherwise there are remaining data to be sent in the buffer, |
806 | | * which means we have to poll before doing so. |
807 | | */ |
808 | 0 | sc_ep_clr(sc, SE_FL_WAIT_DATA); |
809 | 0 | } |
810 | | |
811 | | /* in case of special condition (error, shutdown, end of write...), we |
812 | | * have to notify the task. |
813 | | */ |
814 | 0 | if (likely((sc->flags & SC_FL_SHUT_DONE) || |
815 | 0 | ((oc->flags & CF_WRITE_EVENT) && sc->state < SC_ST_EST) || |
816 | 0 | ((oc->flags & CF_WAKE_WRITE) && |
817 | 0 | ((!co_data(oc) && !oc->to_forward) || |
818 | 0 | !sc_state_in(sc->state, SC_SB_EST))))) { |
819 | 0 | out_wakeup: |
820 | 0 | if (!(sc->flags & SC_FL_DONT_WAKE)) |
821 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO); |
822 | 0 | } |
823 | 0 | } |
824 | 0 | else if (sc_ep_test(sc, SE_FL_T_APPLET)) { |
825 | 0 | if (unlikely(sc->state != SC_ST_EST || (sc->flags & SC_FL_SHUT_DONE))) |
826 | 0 | return; |
827 | | |
828 | | /* we only wake the applet up if it was waiting for some data and is ready to consume it */ |
829 | 0 | if (!sc_ep_test(sc, SE_FL_WAIT_DATA|SE_FL_WONT_CONSUME)) |
830 | 0 | return; |
831 | | |
832 | 0 | if (co_data(oc) || sc_ep_have_ff_data(sc)) { |
833 | | /* (re)start sending */ |
834 | 0 | appctx_wakeup(__sc_appctx(sc)); |
835 | 0 | } |
836 | 0 | } |
837 | 0 | else { |
838 | | /* In theory, it should not happen. This CHECK_IF will be used to validate it (or not...) */ |
839 | 0 | CHECK_IF(!sc_ep_test(sc, SE_FL_T_MUX|SE_FL_T_APPLET)); |
840 | |
|
841 | 0 | if (unlikely(sc->state != SC_ST_EST || (sc->flags & SC_FL_SHUT_DONE))) |
842 | 0 | return; |
843 | | |
844 | 0 | if (!sc_ep_test(sc, SE_FL_WAIT_DATA) || /* not waiting for data */ |
845 | 0 | (!co_data(oc) && !sc_ep_have_ff_data(sc))) /* called with nothing to send ! */ |
846 | 0 | return; |
847 | | |
848 | | /* Otherwise there are remaining data to be sent in the buffer, |
849 | | * so we tell the handler. |
850 | | */ |
851 | 0 | sc_ep_clr(sc, SE_FL_WAIT_DATA); |
852 | 0 | if (!(sc->flags & SC_FL_DONT_WAKE)) |
853 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO); |
854 | 0 | } |
855 | 0 | } |
856 | | |
857 | | /* This function is designed to be called from within the stream handler to |
858 | | * update the input channel's expiration timer and the stream connector's |
859 | | * Rx flags based on the channel's flags. It needs to be called only once |
860 | | * after the channel's flags have settled down, and before they are cleared, |
861 | | * though it doesn't harm to call it as often as desired (it just slightly |
862 | | * hurts performance). It must not be called from outside of the stream |
863 | | * handler, as what it does will be used to compute the stream task's |
864 | | * expiration. |
865 | | */ |
866 | | void sc_update_rx(struct stconn *sc) |
867 | 0 | { |
868 | 0 | struct channel *ic = sc_ic(sc); |
869 | |
|
870 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
871 | 0 | return; |
872 | | |
873 | | /* Unblock the SC if it needs room and the free space is large enough (0 |
874 | | * means it can always be unblocked). Do not unblock it if -1 was |
875 | | * specified. |
876 | | */ |
877 | 0 | if (!sc->room_needed || (sc->room_needed > 0 && channel_recv_max(ic) >= sc->room_needed)) |
878 | 0 | sc_have_room(sc); |
879 | | |
880 | | /* Read not closed, update FD status and timeout for reads */ |
881 | 0 | if (ic->flags & CF_DONT_READ) |
882 | 0 | sc_wont_read(sc); |
883 | 0 | else |
884 | 0 | sc_will_read(sc); |
885 | |
|
886 | 0 | sc_chk_rcv(sc); |
887 | 0 | } |
888 | | |
889 | | /* This function is designed to be called from within the stream handler to |
890 | | * update the output channel's expiration timer and the stream connector's |
891 | | * Tx flags based on the channel's flags. It needs to be called only once |
892 | | * after the channel's flags have settled down, and before they are cleared, |
893 | | * though it doesn't harm to call it as often as desired (it just slightly |
894 | | * hurts performance). It must not be called from outside of the stream |
895 | | * handler, as what it does will be used to compute the stream task's |
896 | | * expiration. |
897 | | */ |
898 | | void sc_update_tx(struct stconn *sc) |
899 | 0 | { |
900 | 0 | struct channel *oc = sc_oc(sc); |
901 | |
|
902 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
903 | 0 | return; |
904 | | |
905 | | /* Write not closed, update FD status and timeout for writes */ |
906 | 0 | if (!co_data(oc)) { |
907 | | /* stop writing */ |
908 | 0 | if (!sc_ep_test(sc, SE_FL_WAIT_DATA)) { |
909 | 0 | if ((sc->flags & SC_FL_SHUT_WANTED) == 0) |
910 | 0 | sc_ep_set(sc, SE_FL_WAIT_DATA); |
911 | 0 | } |
912 | 0 | return; |
913 | 0 | } |
914 | | |
915 | | /* (re)start writing */ |
916 | 0 | sc_ep_clr(sc, SE_FL_WAIT_DATA); |
917 | 0 | } |
918 | | |
919 | | /* This function is the equivalent to sc_update() except that it's |
920 | | * designed to be called from outside the stream handlers, typically the lower |
921 | | * layers (applets, connections) after I/O completion. After updating the stream |
922 | | * interface and timeouts, it will try to forward what can be forwarded, then to |
923 | | * wake the associated task up if an important event requires special handling. |
924 | | * It may update SE_FL_WAIT_DATA and/or SC_FL_NEED_ROOM, that the callers are |
925 | | * encouraged to watch to take appropriate action. |
926 | | * It should not be called from within the stream itself, sc_update() |
927 | | * is designed for this. Please do not statify this function, it's often |
928 | | * present in backtraces, it's useful to recognize it. |
929 | | */ |
930 | | void sc_notify(struct stconn *sc) |
931 | 0 | { |
932 | 0 | struct channel *ic = sc_ic(sc); |
933 | 0 | struct channel *oc = sc_oc(sc); |
934 | 0 | struct stconn *sco = sc_opposite(sc); |
935 | 0 | struct task *task = sc_strm_task(sc); |
936 | | |
937 | | /* process consumer side */ |
938 | 0 | if (!co_data(oc) && !sc_ep_have_ff_data(sc)) { |
939 | 0 | struct connection *conn = sc_conn(sc); |
940 | |
|
941 | 0 | if (((sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED) && |
942 | 0 | (sc->state == SC_ST_EST) && (!conn || !(conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS)))) |
943 | 0 | sc_shutdown(sc); |
944 | 0 | } |
945 | | |
946 | | /* indicate that we may be waiting for data from the output channel or |
947 | | * we're about to close and can't expect more data if SC_FL_SHUT_WANTED is there. |
948 | | */ |
949 | 0 | if (!(sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))) |
950 | 0 | sc_ep_set(sc, SE_FL_WAIT_DATA); |
951 | 0 | else if ((sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED) |
952 | 0 | sc_ep_clr(sc, SE_FL_WAIT_DATA); |
953 | |
|
954 | 0 | if (oc->flags & CF_DONT_READ) |
955 | 0 | sc_wont_read(sco); |
956 | 0 | else |
957 | 0 | sc_will_read(sco); |
958 | | |
959 | | /* Notify the other side when we've injected data into the IC that |
960 | | * needs to be forwarded. We can do fast-forwarding as soon as there |
961 | | * are output data, but we avoid doing this if some of the data are |
962 | | * not yet scheduled for being forwarded, because it is very likely |
963 | | * that it will be done again immediately afterwards once the following |
964 | | * data are parsed (eg: HTTP chunking). We only clear SC_FL_NEED_ROOM |
965 | | * once we've emptied *some* of the output buffer, and not just when |
966 | | * there is available room, because applets are often forced to stop |
967 | | * before the buffer is full. We must not stop based on input data |
968 | | * alone because an HTTP parser might need more data to complete the |
969 | | * parsing. |
970 | | */ |
971 | 0 | if (sc_ep_have_ff_data(sc_opposite(sc)) || |
972 | 0 | (co_data(ic) && sc_ep_test(sco, SE_FL_WAIT_DATA) && |
973 | 0 | (!HAS_DATA_FILTERS(__sc_strm(sc), ic) || channel_input_data(ic) == 0) && |
974 | 0 | (!(sc->flags & SC_FL_SND_EXP_MORE) || channel_full(ic, co_data(ic)) || channel_input_data(ic) == 0))) { |
975 | 0 | int new_len, last_len; |
976 | |
|
977 | 0 | last_len = co_data(ic) + sc_ep_ff_data(sco); |
978 | 0 | sc_chk_snd(sco); |
979 | 0 | new_len = co_data(ic) + sc_ep_ff_data(sco); |
980 | | |
981 | | /* check if the consumer has freed some space either in the |
982 | | * buffer or in the pipe. |
983 | | */ |
984 | 0 | if (!sc->room_needed || (new_len < last_len && (sc->room_needed < 0 || channel_recv_max(ic) >= sc->room_needed))) |
985 | 0 | sc_have_room(sc); |
986 | 0 | } |
987 | |
|
988 | 0 | if (!(ic->flags & CF_DONT_READ)) |
989 | 0 | sc_will_read(sc); |
990 | |
|
991 | 0 | sc_chk_rcv(sc); |
992 | 0 | sc_chk_rcv(sco); |
993 | | |
994 | | /* wake the task up only when needed */ |
995 | 0 | if (/* changes on the production side that must be handled: |
996 | | * - An error on receipt: SC_FL_ERROR |
997 | | * - A read event: shutdown for reads (CF_READ_EVENT + EOS/ABRT_DONE) |
998 | | * end of input (CF_READ_EVENT + SC_FL_EOI) |
999 | | * data received and no fast-forwarding (CF_READ_EVENT + !to_forward) |
1000 | | * read event while consumer side is not established (CF_READ_EVENT + sco->state != SC_ST_EST) |
1001 | | */ |
1002 | 0 | ((ic->flags & CF_READ_EVENT) && ((sc->flags & SC_FL_EOI) || (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) || !ic->to_forward || sco->state != SC_ST_EST)) || |
1003 | 0 | (sc->flags & SC_FL_ERROR) || |
1004 | | |
1005 | | /* changes on the consumption side */ |
1006 | 0 | sc_ep_test(sc, SE_FL_ERR_PENDING) || |
1007 | 0 | ((oc->flags & CF_WRITE_EVENT) && |
1008 | 0 | ((sc->state < SC_ST_EST) || |
1009 | 0 | (sc->flags & SC_FL_SHUT_DONE) || |
1010 | 0 | (((oc->flags & CF_WAKE_WRITE) || |
1011 | 0 | (!(oc->flags & CF_AUTO_CLOSE) && |
1012 | 0 | !(sc->flags & (SC_FL_SHUT_WANTED|SC_FL_SHUT_DONE)))) && |
1013 | 0 | (sco->state != SC_ST_EST || |
1014 | 0 | (!co_data(oc) && !oc->to_forward)))))) { |
1015 | 0 | task_wakeup(task, TASK_WOKEN_IO); |
1016 | 0 | } |
1017 | 0 | else { |
1018 | | /* Update expiration date for the task and requeue it if not already expired. |
1019 | | * Only I/O timeouts are evaluated. The stream is responsible of others. |
1020 | | */ |
1021 | 0 | if (!tick_is_expired(task->expire, now_ms)) { |
1022 | 0 | task->expire = tick_first(task->expire, sc_ep_rcv_ex(sc)); |
1023 | 0 | task->expire = tick_first(task->expire, sc_ep_snd_ex(sc)); |
1024 | 0 | task->expire = tick_first(task->expire, sc_ep_rcv_ex(sco)); |
1025 | 0 | task->expire = tick_first(task->expire, sc_ep_snd_ex(sco)); |
1026 | |
|
1027 | 0 | BUG_ON(tick_is_expired(task->expire, now_ms)); |
1028 | 0 | task_queue(task); |
1029 | 0 | } |
1030 | 0 | } |
1031 | |
|
1032 | 0 | if (ic->flags & CF_READ_EVENT) |
1033 | 0 | sc->flags &= ~SC_FL_RCV_ONCE; |
1034 | 0 | } |
1035 | | |
1036 | | /* |
1037 | | * This function propagates an end-of-stream received on a socket-based connection. |
1038 | | * It updates the stream connector. If the stream connector has SC_FL_NOHALF, |
1039 | | * the close is also forwarded to the write side as an abort. |
1040 | | */ |
1041 | | static void sc_conn_eos(struct stconn *sc) |
1042 | 0 | { |
1043 | 0 | struct channel *ic = sc_ic(sc); |
1044 | |
|
1045 | 0 | BUG_ON(!sc_conn(sc)); |
1046 | |
|
1047 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
1048 | 0 | return; |
1049 | 0 | sc->flags |= SC_FL_EOS; |
1050 | 0 | ic->flags |= CF_READ_EVENT; |
1051 | 0 | sc_ep_report_read_activity(sc); |
1052 | 0 | sc_report_term_evt(sc, (sc->flags & SC_FL_EOI ? strm_tevt_type_eos: strm_tevt_type_truncated_eos)); |
1053 | 0 | if (sc->state != SC_ST_EST) |
1054 | 0 | return; |
1055 | | |
1056 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
1057 | 0 | goto do_close; |
1058 | | |
1059 | 0 | if (sc_cond_forward_shut(sc)) { |
1060 | | /* we want to immediately forward this close to the write side */ |
1061 | | /* force flag on ssl to keep stream in cache */ |
1062 | 0 | goto do_close; |
1063 | 0 | } |
1064 | | |
1065 | | /* otherwise that's just a normal read shutdown */ |
1066 | 0 | return; |
1067 | | |
1068 | 0 | do_close: |
1069 | | /* OK we completely close the socket here just as if we went through sc_shut[rw]() */ |
1070 | 0 | se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT); |
1071 | |
|
1072 | 0 | sc->flags &= ~SC_FL_SHUT_WANTED; |
1073 | 0 | sc->flags |= SC_FL_SHUT_DONE; |
1074 | |
|
1075 | 0 | sc->state = SC_ST_DIS; |
1076 | 0 | if (sc->flags & SC_FL_ISBACK) |
1077 | 0 | __sc_strm(sc)->conn_exp = TICK_ETERNITY; |
1078 | 0 | return; |
1079 | 0 | } |
1080 | | |
1081 | | /* |
1082 | | * This is the callback which is called by the connection layer to receive data |
1083 | | * into the buffer from the connection. It iterates over the mux layer's |
1084 | | * rcv_buf function. Please do not statify this function, it's often present in |
1085 | | * backtraces, it's useful to recognize it. |
1086 | | */ |
1087 | | int sc_conn_recv(struct stconn *sc) |
1088 | 0 | { |
1089 | 0 | struct connection *conn = __sc_conn(sc); |
1090 | 0 | struct channel *ic = sc_ic(sc); |
1091 | 0 | int ret, max, cur_read = 0; |
1092 | 0 | int read_poll = MAX_READ_POLL_LOOPS; |
1093 | 0 | int flags = 0; |
1094 | | |
1095 | | /* If not established yet, do nothing. */ |
1096 | 0 | if (sc->state != SC_ST_EST) |
1097 | 0 | return 0; |
1098 | | |
1099 | | /* If another call to sc_conn_recv() failed, and we subscribed to |
1100 | | * recv events already, give up now. |
1101 | | */ |
1102 | 0 | if ((sc->wait_event.events & SUB_RETRY_RECV) || sc_waiting_room(sc)) |
1103 | 0 | return 0; |
1104 | | |
1105 | | /* maybe we were called immediately after an asynchronous abort */ |
1106 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
1107 | 0 | return 1; |
1108 | | |
1109 | | /* we must wait because the mux is not installed yet */ |
1110 | 0 | if (!conn->mux) |
1111 | 0 | return 0; |
1112 | | |
1113 | | /* stop immediately on errors. Note that we DON'T want to stop on |
1114 | | * POLL_ERR, as the poller might report a write error while there |
1115 | | * are still data available in the recv buffer. This typically |
1116 | | * happens when we send too large a request to a backend server |
1117 | | * which rejects it before reading it all. |
1118 | | */ |
1119 | 0 | if (!sc_ep_test(sc, SE_FL_RCV_MORE)) { |
1120 | 0 | if (!conn_xprt_ready(conn)) |
1121 | 0 | return 0; |
1122 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
1123 | 0 | goto end_recv; |
1124 | 0 | } |
1125 | | |
1126 | | /* prepare to detect if the mux needs more room */ |
1127 | 0 | sc_ep_clr(sc, SE_FL_WANT_ROOM); |
1128 | |
|
1129 | 0 | channel_check_idletimer(ic); |
1130 | |
|
1131 | | #if defined(USE_LINUX_SPLICE) |
1132 | | /* Detect if the splicing is possible depending on the stream policy */ |
1133 | | if ((global.tune.options & GTUNE_USE_SPLICE) && |
1134 | | (ic->to_forward >= MIN_SPLICE_FORWARD) && |
1135 | | ((!(sc->flags & SC_FL_ISBACK) && ((strm_fe(__sc_strm(sc))->options2|__sc_strm(sc)->be->options2) & PR_O2_SPLIC_REQ)) || |
1136 | | ((sc->flags & SC_FL_ISBACK) && ((strm_fe(__sc_strm(sc))->options2|__sc_strm(sc)->be->options2) & PR_O2_SPLIC_RTR)) || |
1137 | | ((ic->flags & CF_STREAMER_FAST) && ((strm_sess(__sc_strm(sc))->fe->options2|__sc_strm(sc)->be->options2) & PR_O2_SPLIC_AUT)))) |
1138 | | flags |= CO_RFL_MAY_SPLICE; |
1139 | | #endif |
1140 | | |
1141 | | /* First, let's see if we may fast-forward data from a side to the other |
1142 | | * one without using the channel buffer. |
1143 | | */ |
1144 | 0 | if (sc_is_fastfwd_supported(sc)) { |
1145 | 0 | if (channel_data(ic)) { |
1146 | | /* We're embarrassed, there are already data pending in |
1147 | | * the buffer and we don't want to have them at two |
1148 | | * locations at a time. Let's indicate we need some |
1149 | | * place and ask the consumer to hurry. |
1150 | | */ |
1151 | 0 | flags |= CO_RFL_BUF_FLUSH; |
1152 | 0 | goto abort_fastfwd; |
1153 | 0 | } |
1154 | 0 | sc_ep_fwd_kip(sc, sc_opposite(sc)); |
1155 | 0 | ret = CALL_MUX_WITH_RET(conn->mux, fastfwd(sc, ic->to_forward, flags)); |
1156 | 0 | if (ret < 0) |
1157 | 0 | goto abort_fastfwd; |
1158 | 0 | else if (ret > 0) { |
1159 | 0 | if (ic->to_forward != CHN_INFINITE_FORWARD) |
1160 | 0 | ic->to_forward -= ret; |
1161 | 0 | sc->bytes_in += ret; |
1162 | 0 | cur_read += ret; |
1163 | 0 | ic->flags |= CF_READ_EVENT; |
1164 | 0 | } |
1165 | | |
1166 | 0 | if (sc_ep_test(sc, SE_FL_EOS | SE_FL_ERROR)) |
1167 | 0 | goto end_recv; |
1168 | | |
1169 | 0 | if (sc_ep_test(sc, SE_FL_WANT_ROOM)) |
1170 | 0 | sc_need_room(sc, -1); |
1171 | |
|
1172 | 0 | if (sc_ep_test(sc, SE_FL_MAY_FASTFWD_PROD) && ic->to_forward) |
1173 | 0 | goto done_recv; |
1174 | 0 | } |
1175 | | |
1176 | 0 | abort_fastfwd: |
1177 | | /* now we'll need a input buffer for the stream */ |
1178 | 0 | if (!sc_alloc_ibuf(sc, &(__sc_strm(sc)->buffer_wait))) |
1179 | 0 | goto end_recv; |
1180 | | |
1181 | | /* For an HTX stream, if the buffer is stuck (no output data with some |
1182 | | * input data) and if the HTX message is fragmented or if its free space |
1183 | | * wraps, we force an HTX deframentation. It is a way to have a |
1184 | | * contiguous free space nad to let the mux to copy as much data as |
1185 | | * possible. |
1186 | | * |
1187 | | * NOTE: A possible optim may be to let the mux decides if defrag is |
1188 | | * required or not, depending on amount of data to be xferred. |
1189 | | */ |
1190 | 0 | if (IS_HTX_STRM(__sc_strm(sc)) && !co_data(ic)) { |
1191 | 0 | struct htx *htx = htxbuf(&ic->buf); |
1192 | |
|
1193 | 0 | if (htx_is_not_empty(htx) && ((htx->flags & HTX_FL_FRAGMENTED) || htx_space_wraps(htx))) |
1194 | 0 | htx_defrag(htx, NULL, 0); |
1195 | 0 | } |
1196 | | |
1197 | | /* Instruct the mux it must subscribed for read events */ |
1198 | 0 | if (!(sc->flags & SC_FL_ISBACK) && /* for frontend conns only */ |
1199 | 0 | (sc_opposite(sc)->state != SC_ST_INI) && /* before backend connection setup */ |
1200 | 0 | proxy_abrt_close(__sc_strm(sc)->be)) /* if abortonclose option is set for the current backend */ |
1201 | 0 | flags |= CO_RFL_KEEP_RECV; |
1202 | | |
1203 | | /* Important note : if we're called with POLL_IN|POLL_HUP, it means the read polling |
1204 | | * was enabled, which implies that the recv buffer was not full. So we have a guarantee |
1205 | | * that if such an event is not handled above in splice, it will be handled here by |
1206 | | * recv(). |
1207 | | */ |
1208 | 0 | while (sc_ep_test(sc, SE_FL_RCV_MORE) || |
1209 | 0 | (!(conn->flags & CO_FL_HANDSHAKE) && |
1210 | 0 | (!sc_ep_test(sc, SE_FL_ERROR | SE_FL_EOS)) && !(sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)))) { |
1211 | 0 | int cur_flags = flags; |
1212 | | |
1213 | | /* Compute transient CO_RFL_* flags */ |
1214 | 0 | if (co_data(ic)) { |
1215 | 0 | cur_flags |= (CO_RFL_BUF_WET | CO_RFL_BUF_NOT_STUCK); |
1216 | 0 | } |
1217 | | |
1218 | | /* <max> may be null. This is the mux responsibility to set |
1219 | | * SE_FL_RCV_MORE on the SC if more space is needed. |
1220 | | */ |
1221 | 0 | max = channel_recv_max(ic); |
1222 | 0 | if (b_is_small(sc_ib(sc)) || ((ic->flags & CF_WROTE_DATA) && b_is_large(sc_ib(sc)))) |
1223 | 0 | max = 0; |
1224 | 0 | ret = CALL_MUX_WITH_RET(conn->mux, rcv_buf(sc, &ic->buf, max, cur_flags)); |
1225 | |
|
1226 | 0 | if (sc_ep_test(sc, SE_FL_WANT_ROOM)) { |
1227 | | /* SE_FL_WANT_ROOM must not be reported if the channel's |
1228 | | * buffer is empty. |
1229 | | */ |
1230 | 0 | BUG_ON(c_empty(ic)); |
1231 | |
|
1232 | 0 | sc_need_room(sc, channel_recv_max(ic) + 1); |
1233 | | /* Add READ_PARTIAL because some data are pending but |
1234 | | * cannot be xferred to the channel |
1235 | | */ |
1236 | 0 | ic->flags |= CF_READ_EVENT; |
1237 | 0 | sc_ep_report_read_activity(sc); |
1238 | 0 | } |
1239 | |
|
1240 | 0 | if (ret <= 0) { |
1241 | | /* if we refrained from reading because we asked for a |
1242 | | * flush to satisfy rcv_pipe(), we must not subscribe |
1243 | | * and instead report that there's not enough room |
1244 | | * here to proceed. |
1245 | | */ |
1246 | 0 | if (flags & CO_RFL_BUF_FLUSH) |
1247 | 0 | sc_need_room(sc, -1); |
1248 | 0 | break; |
1249 | 0 | } |
1250 | | |
1251 | 0 | cur_read += ret; |
1252 | | |
1253 | | /* if we're allowed to directly forward data, we must update ->o */ |
1254 | 0 | if (ic->to_forward && !(sc_opposite(sc)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))) { |
1255 | 0 | unsigned long fwd = ret; |
1256 | 0 | if (ic->to_forward != CHN_INFINITE_FORWARD) { |
1257 | 0 | if (fwd > ic->to_forward) |
1258 | 0 | fwd = ic->to_forward; |
1259 | 0 | ic->to_forward -= fwd; |
1260 | 0 | } |
1261 | 0 | c_adv(ic, fwd); |
1262 | 0 | } |
1263 | |
|
1264 | 0 | ic->flags |= CF_READ_EVENT; |
1265 | 0 | sc->bytes_in += ret; |
1266 | | |
1267 | | /* End-of-input reached, we can leave. In this case, it is |
1268 | | * important to break the loop to not block the SC because of |
1269 | | * the channel's policies.This way, we are still able to receive |
1270 | | * shutdowns. |
1271 | | */ |
1272 | 0 | if (sc_ep_test(sc, SE_FL_EOI)) |
1273 | 0 | break; |
1274 | | |
1275 | 0 | if ((sc->flags & SC_FL_RCV_ONCE) || --read_poll <= 0) { |
1276 | | /* we don't expect to read more data */ |
1277 | 0 | sc_wont_read(sc); |
1278 | 0 | break; |
1279 | 0 | } |
1280 | | |
1281 | | /* if too many bytes were missing from last read, it means that |
1282 | | * it's pointless trying to read again because the system does |
1283 | | * not have them in buffers. |
1284 | | */ |
1285 | 0 | if (ret < max) { |
1286 | | /* if a streamer has read few data, it may be because we |
1287 | | * have exhausted system buffers. It's not worth trying |
1288 | | * again. |
1289 | | */ |
1290 | 0 | if (ic->flags & CF_STREAMER) { |
1291 | | /* we're stopped by the channel's policy */ |
1292 | 0 | sc_wont_read(sc); |
1293 | 0 | break; |
1294 | 0 | } |
1295 | | |
1296 | | /* if we read a large block smaller than what we requested, |
1297 | | * it's almost certain we'll never get anything more. |
1298 | | */ |
1299 | 0 | if (ret >= global.tune.recv_enough) { |
1300 | | /* we're stopped by the channel's policy */ |
1301 | 0 | sc_wont_read(sc); |
1302 | 0 | break; |
1303 | 0 | } |
1304 | 0 | } |
1305 | | |
1306 | | /* if we are waiting for more space, don't try to read more data |
1307 | | * right now. |
1308 | | */ |
1309 | 0 | if (sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM)) |
1310 | 0 | break; |
1311 | 0 | } /* while !flags */ |
1312 | | |
1313 | 0 | done_recv: |
1314 | 0 | if (!cur_read) |
1315 | 0 | se_have_no_more_data(sc->sedesc); |
1316 | 0 | else { |
1317 | 0 | channel_check_xfer(ic, cur_read); |
1318 | 0 | sc_ep_report_read_activity(sc); |
1319 | 0 | } |
1320 | |
|
1321 | 0 | end_recv: |
1322 | 0 | ret = (cur_read != 0); |
1323 | | |
1324 | | /* Report EOI on the channel if it was reached from the mux point of |
1325 | | * view. */ |
1326 | 0 | if (sc_ep_test(sc, SE_FL_EOI) && !(sc->flags & SC_FL_EOI)) { |
1327 | 0 | sc_ep_report_read_activity(sc); |
1328 | 0 | sc->flags |= SC_FL_EOI; |
1329 | 0 | ic->flags |= CF_READ_EVENT; |
1330 | 0 | ret = 1; |
1331 | 0 | } |
1332 | |
|
1333 | 0 | if (sc_ep_test(sc, SE_FL_EOS)) { |
1334 | | /* we received a shutdown */ |
1335 | 0 | if (ic->flags & CF_AUTO_CLOSE) |
1336 | 0 | sc_schedule_shutdown(sc_opposite(sc)); |
1337 | 0 | sc_conn_eos(sc); |
1338 | 0 | ret = 1; |
1339 | 0 | } |
1340 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) { |
1341 | 0 | sc->flags |= SC_FL_ERROR; |
1342 | 0 | if (!(sc->flags & SC_FL_EOS)) |
1343 | 0 | sc_report_term_evt(sc, (sc->flags & SC_FL_EOI ? strm_tevt_type_rcv_err: strm_tevt_type_truncated_rcv_err)); |
1344 | 0 | ret = 1; |
1345 | 0 | } |
1346 | | |
1347 | | /* Ensure sc_conn_process() is called if waiting on handshake. */ |
1348 | 0 | if (!(conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS)) && |
1349 | 0 | sc_ep_test(sc, SE_FL_WAIT_FOR_HS)) { |
1350 | 0 | ret = 1; |
1351 | 0 | } |
1352 | |
|
1353 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ERROR)) { |
1354 | | /* No more data are expected at this stage */ |
1355 | 0 | se_have_no_more_data(sc->sedesc); |
1356 | 0 | } |
1357 | 0 | else if (!cur_read && |
1358 | 0 | !(sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM)) && |
1359 | 0 | !(sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE))) { |
1360 | | /* Subscribe to receive events if we're blocking on I/O. Nothing |
1361 | | * was received and it was not because of a blocking |
1362 | | * condition. |
1363 | | */ |
1364 | 0 | conn->mux->subscribe(sc, SUB_RETRY_RECV, &sc->wait_event); |
1365 | 0 | se_have_no_more_data(sc->sedesc); |
1366 | 0 | } |
1367 | 0 | else if (sc->flags & SC_FL_EOI) { |
1368 | | /* No more data are expected at this stage, except if abortonclose is enabled */ |
1369 | 0 | if (!(flags & CO_RFL_KEEP_RECV)) |
1370 | 0 | se_have_no_more_data(sc->sedesc); |
1371 | 0 | else |
1372 | 0 | se_have_more_data(sc->sedesc); |
1373 | 0 | } |
1374 | 0 | else { |
1375 | | /* The mux may have more data to deliver. Be sure to be able to |
1376 | | * ask it ASAP |
1377 | | */ |
1378 | 0 | se_have_more_data(sc->sedesc); |
1379 | 0 | ret = 1; |
1380 | 0 | } |
1381 | |
|
1382 | 0 | return ret; |
1383 | 0 | } |
1384 | | |
1385 | | /* This tries to perform a synchronous receive on the stream connector to |
1386 | | * try to collect last arrived data. In practice it's only implemented on |
1387 | | * stconns. Returns 0 if nothing was done, non-zero if new data or a |
1388 | | * shutdown were collected. This may result on some delayed receive calls |
1389 | | * to be programmed and performed later, though it doesn't provide any |
1390 | | * such guarantee. |
1391 | | */ |
1392 | | int sc_conn_sync_recv(struct stconn *sc) |
1393 | 0 | { |
1394 | 0 | if (!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST)) |
1395 | 0 | return 0; |
1396 | | |
1397 | 0 | if (!sc_mux_ops(sc)) |
1398 | 0 | return 0; // only stconns are supported |
1399 | | |
1400 | 0 | if (sc->wait_event.events & SUB_RETRY_RECV) |
1401 | 0 | return 0; // already subscribed |
1402 | | |
1403 | 0 | if (!sc_is_recv_allowed(sc)) |
1404 | 0 | return 0; // already failed |
1405 | | |
1406 | 0 | return sc_conn_recv(sc); |
1407 | 0 | } |
1408 | | |
1409 | | /* |
1410 | | * This function is called to send buffer data to a stream socket. |
1411 | | * It calls the mux layer's snd_buf function. It relies on the |
1412 | | * caller to commit polling changes. The caller should check conn->flags |
1413 | | * for errors. Please do not statify this function, it's often present in |
1414 | | * backtraces, it's useful to recognize it. |
1415 | | */ |
1416 | | int sc_conn_send(struct stconn *sc) |
1417 | 0 | { |
1418 | 0 | struct connection *conn = __sc_conn(sc); |
1419 | 0 | struct stconn *sco = sc_opposite(sc); |
1420 | 0 | struct stream *s = __sc_strm(sc); |
1421 | 0 | struct channel *oc = sc_oc(sc); |
1422 | 0 | int ret; |
1423 | 0 | int did_send = 0; |
1424 | |
|
1425 | 0 | if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING) || sc_is_conn_error(sc)) { |
1426 | | /* We're probably there because the tasklet was woken up, |
1427 | | * but process_stream() ran before, detected there were an |
1428 | | * error and put the SC back to SC_ST_TAR. There's still |
1429 | | * CO_FL_ERROR on the connection but we don't want to add |
1430 | | * SE_FL_ERROR back, so give up |
1431 | | */ |
1432 | 0 | if (sc->state < SC_ST_CON) |
1433 | 0 | return 0; |
1434 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); |
1435 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
1436 | 0 | sc->flags |= SC_FL_ERROR; |
1437 | 0 | if (co_data(oc) || sc_ep_have_ff_data(sc)) |
1438 | 0 | sc_ep_report_blocked_send(sc, 0); |
1439 | 0 | return 1; |
1440 | 0 | } |
1441 | | |
1442 | | /* We're already waiting to be able to send, give up */ |
1443 | 0 | if (sc->wait_event.events & SUB_RETRY_SEND) |
1444 | 0 | return 0; |
1445 | | |
1446 | | /* we might have been called just after an asynchronous shutw */ |
1447 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
1448 | 0 | return 1; |
1449 | | |
1450 | | /* we must wait because the mux is not installed yet */ |
1451 | 0 | if (!conn->mux) |
1452 | 0 | return 0; |
1453 | | |
1454 | 0 | sc_ep_fwd_kip(sco, sc); |
1455 | |
|
1456 | 0 | if (sc_ep_have_ff_data(sc)) { |
1457 | 0 | unsigned int send_flag = 0; |
1458 | |
|
1459 | 0 | if ((!(sc->flags & (SC_FL_SND_ASAP|SC_FL_SND_NEVERWAIT)) && |
1460 | 0 | ((oc->to_forward && oc->to_forward != CHN_INFINITE_FORWARD) || |
1461 | 0 | (sc->flags & SC_FL_SND_EXP_MORE) || |
1462 | 0 | (IS_HTX_STRM(s) && |
1463 | 0 | (!(sco->flags & (SC_FL_EOI|SC_FL_EOS|SC_FL_ABRT_DONE)) && htx_expect_more(htxbuf(&oc->buf)))))) || |
1464 | 0 | ((oc->flags & CF_ISRESP) && |
1465 | 0 | (oc->flags & CF_AUTO_CLOSE) && |
1466 | 0 | (sc->flags & SC_FL_SHUT_WANTED))) |
1467 | 0 | send_flag |= CO_SFL_MSG_MORE; |
1468 | |
|
1469 | 0 | if (oc->flags & CF_STREAMER) |
1470 | 0 | send_flag |= CO_SFL_STREAMER; |
1471 | |
|
1472 | 0 | ret = CALL_MUX_WITH_RET(conn->mux, resume_fastfwd(sc, send_flag)); |
1473 | 0 | if (ret > 0) { |
1474 | 0 | sc->bytes_out += ret; |
1475 | 0 | did_send = 1; |
1476 | 0 | } |
1477 | |
|
1478 | 0 | if (sc_ep_have_ff_data(sc)) |
1479 | 0 | goto end; |
1480 | 0 | } |
1481 | | |
1482 | | /* At this point, the pipe is empty, but we may still have data pending |
1483 | | * in the normal buffer. |
1484 | | */ |
1485 | 0 | if (co_data(oc)) { |
1486 | | /* when we're here, we already know that there is no spliced |
1487 | | * data left, and that there are sendable buffered data. |
1488 | | */ |
1489 | | |
1490 | | /* check if we want to inform the kernel that we're interested in |
1491 | | * sending more data after this call. We want this if : |
1492 | | * - we're about to close after this last send and want to merge |
1493 | | * the ongoing FIN with the last segment. |
1494 | | * - we know we can't send everything at once and must get back |
1495 | | * here because of unaligned data |
1496 | | * - there is still a finite amount of data to forward |
1497 | | * The test is arranged so that the most common case does only 2 |
1498 | | * tests. |
1499 | | */ |
1500 | 0 | unsigned int send_flag = 0; |
1501 | |
|
1502 | 0 | if ((!(sc->flags & (SC_FL_SND_ASAP|SC_FL_SND_NEVERWAIT)) && |
1503 | 0 | ((oc->to_forward && oc->to_forward != CHN_INFINITE_FORWARD) || |
1504 | 0 | (sc->flags & SC_FL_SND_EXP_MORE) || |
1505 | 0 | (IS_HTX_STRM(s) && |
1506 | 0 | (!(sco->flags & (SC_FL_EOI|SC_FL_EOS|SC_FL_ABRT_DONE)) && htx_expect_more(htxbuf(&oc->buf)))))) || |
1507 | 0 | ((oc->flags & CF_ISRESP) && |
1508 | 0 | (oc->flags & CF_AUTO_CLOSE) && |
1509 | 0 | (sc->flags & SC_FL_SHUT_WANTED))) |
1510 | 0 | send_flag |= CO_SFL_MSG_MORE; |
1511 | |
|
1512 | 0 | if (oc->flags & CF_STREAMER) |
1513 | 0 | send_flag |= CO_SFL_STREAMER; |
1514 | |
|
1515 | 0 | if ((s->flags & SF_TXN_MASK) == SF_TXN_HTTP && (s->txn.http->flags & TX_L7_RETRY) && !b_data(&s->txn.http->l7_buffer)) { |
1516 | | /* If we want to be able to do L7 retries, copy |
1517 | | * the data we're about to send, so that we are able |
1518 | | * to resend them if needed |
1519 | | */ |
1520 | | /* Try to allocate a buffer if we had none. |
1521 | | * If it fails, the next test will just |
1522 | | * disable the l7 retries by setting |
1523 | | * l7_conn_retries to 0. |
1524 | | */ |
1525 | 0 | if (s->txn.http->req.msg_state != HTTP_MSG_DONE || b_is_large(&oc->buf)) |
1526 | 0 | s->txn.http->flags &= ~TX_L7_RETRY; |
1527 | 0 | else { |
1528 | 0 | if (!(s->be->options2 & PR_O2_USE_SBUF_L7_RETRY) || |
1529 | 0 | !htx_copy_to_small_buffer(&s->txn.http->l7_buffer, &oc->buf)) { |
1530 | 0 | if (b_alloc(&s->txn.http->l7_buffer, DB_UNLIKELY) == NULL) |
1531 | 0 | s->txn.http->flags &= ~TX_L7_RETRY; |
1532 | 0 | else { |
1533 | 0 | memcpy(b_orig(&s->txn.http->l7_buffer), |
1534 | 0 | b_orig(&oc->buf), |
1535 | 0 | b_size(&oc->buf)); |
1536 | 0 | } |
1537 | 0 | } |
1538 | |
|
1539 | 0 | if (s->txn.http->flags & TX_L7_RETRY) { |
1540 | 0 | s->txn.http->l7_buffer.head = co_data(oc); |
1541 | 0 | b_set_data(&s->txn.http->l7_buffer, |
1542 | 0 | co_data(oc)); |
1543 | 0 | } |
1544 | 0 | } |
1545 | 0 | } |
1546 | |
|
1547 | 0 | if ((sc->flags & SC_FL_SHUT_WANTED) && co_data(oc) == c_data(oc)) |
1548 | 0 | send_flag |= CO_SFL_LAST_DATA; |
1549 | |
|
1550 | 0 | ret = CALL_MUX_WITH_RET(conn->mux, snd_buf(sc, &oc->buf, co_data(oc), send_flag)); |
1551 | 0 | if (ret > 0) { |
1552 | 0 | did_send = 1; |
1553 | 0 | c_rew(oc, ret); |
1554 | 0 | c_realign_if_empty(oc); |
1555 | 0 | sc->bytes_out += ret; |
1556 | 0 | if (!co_data(oc)) { |
1557 | | /* Always clear both flags once everything has been sent, they're one-shot */ |
1558 | 0 | sc->flags &= ~(SC_FL_SND_ASAP|SC_FL_SND_EXP_MORE); |
1559 | 0 | } |
1560 | | /* if some data remain in the buffer, it's only because the |
1561 | | * system buffers are full, we will try next time. |
1562 | | */ |
1563 | 0 | } |
1564 | 0 | } |
1565 | |
|
1566 | 0 | end: |
1567 | 0 | if (did_send) { |
1568 | 0 | oc->flags |= CF_WRITE_EVENT | CF_WROTE_DATA; |
1569 | 0 | if (sc->state == SC_ST_CON) |
1570 | 0 | sc->state = SC_ST_RDY; |
1571 | 0 | } |
1572 | |
|
1573 | 0 | if (!sco->room_needed || (did_send && (sco->room_needed < 0 || channel_recv_max(sc_oc(sc)) >= sco->room_needed))) |
1574 | 0 | sc_have_room(sco); |
1575 | |
|
1576 | 0 | if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING)) { |
1577 | 0 | oc->flags |= CF_WRITE_EVENT; |
1578 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); |
1579 | 0 | sc_report_term_evt(sc, strm_tevt_type_snd_err); |
1580 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
1581 | 0 | sc->flags |= SC_FL_ERROR; |
1582 | 0 | return 1; |
1583 | 0 | } |
1584 | | |
1585 | | /* FIXME: Must be reviewed for FF */ |
1586 | 0 | if (!co_data(oc) && !sc_ep_have_ff_data(sc)) { |
1587 | 0 | if (did_send) |
1588 | 0 | sc_ep_report_send_activity(sc); |
1589 | | /* If fast-forwarding is blocked, unblock it now to check for |
1590 | | * receive on the other side |
1591 | | */ |
1592 | 0 | if (sc->sedesc->iobuf.flags & IOBUF_FL_FF_BLOCKED) { |
1593 | 0 | sc->sedesc->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED; |
1594 | 0 | sc_have_room(sco); |
1595 | 0 | did_send = 1; |
1596 | 0 | } |
1597 | 0 | } |
1598 | 0 | else { |
1599 | | /* We couldn't send all of our data, let the mux know we'd like to send more */ |
1600 | 0 | conn->mux->subscribe(sc, SUB_RETRY_SEND, &sc->wait_event); |
1601 | 0 | if (sc_state_in(sc->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) |
1602 | 0 | sc_ep_report_blocked_send(sc, did_send); |
1603 | 0 | } |
1604 | |
|
1605 | 0 | return did_send; |
1606 | 0 | } |
1607 | | |
1608 | | /* perform a synchronous send() for the stream connector. The CF_WRITE_EVENT |
1609 | | * flag are cleared prior to the attempt, and will possibly be updated in case |
1610 | | * of success. |
1611 | | */ |
1612 | | int sc_conn_sync_send(struct stconn *sc) |
1613 | 0 | { |
1614 | 0 | struct channel *oc = sc_oc(sc); |
1615 | 0 | int did_send = 0; |
1616 | |
|
1617 | 0 | oc->flags &= ~CF_WRITE_EVENT; |
1618 | |
|
1619 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
1620 | 0 | goto end; |
1621 | | |
1622 | 0 | if (!co_data(oc)) |
1623 | 0 | goto end; |
1624 | | |
1625 | 0 | if (!sc_state_in(sc->state, SC_SB_CON|SC_SB_RDY|SC_SB_EST)) |
1626 | 0 | goto end; |
1627 | | |
1628 | 0 | if (!sc_mux_ops(sc)) |
1629 | 0 | goto end; |
1630 | | |
1631 | 0 | did_send = sc_conn_send(sc); |
1632 | 0 | if (oc->flags & CF_WRITE_EVENT) |
1633 | 0 | oc->flags |= CF_WAKE_ONCE; |
1634 | 0 | end: |
1635 | 0 | return did_send; |
1636 | 0 | } |
1637 | | |
1638 | | /* Called by I/O handlers after completion.. It propagates |
1639 | | * connection flags to the stream connector, updates the stream (which may or |
1640 | | * may not take this opportunity to try to forward data), then update the |
1641 | | * connection's polling based on the channels and stream connector's final |
1642 | | * states. The function always returns 0. Please do not statify this function, |
1643 | | * it's often present in backtraces, it's useful to recognize it. |
1644 | | */ |
1645 | | int sc_conn_process(struct stconn *sc) |
1646 | 0 | { |
1647 | 0 | struct connection *conn = __sc_conn(sc); |
1648 | 0 | struct channel *ic = sc_ic(sc); |
1649 | 0 | struct channel *oc = sc_oc(sc); |
1650 | |
|
1651 | 0 | BUG_ON(!conn); |
1652 | | |
1653 | | /* If we have data to send, try it now */ |
1654 | 0 | if ((co_data(oc) || sc_ep_have_ff_data(sc)) && |
1655 | 0 | !(sc->wait_event.events & SUB_RETRY_SEND)) |
1656 | 0 | sc_conn_send(sc); |
1657 | | |
1658 | | /* First step, report to the stream connector what was detected at the |
1659 | | * connection layer : errors and connection establishment. |
1660 | | * Only add SC_FL_ERROR if we're connected, or we're attempting to |
1661 | | * connect, we may get there because we got woken up, but only run |
1662 | | * after process_stream() noticed there were an error, and decided |
1663 | | * to retry to connect, the connection may still have CO_FL_ERROR, |
1664 | | * and we don't want to add SC_FL_ERROR back |
1665 | | * |
1666 | | * Note: This test is only required because sc_conn_process is also the SI |
1667 | | * wake callback. Otherwise sc_conn_recv()/sc_conn_send() already take |
1668 | | * care of it. |
1669 | | */ |
1670 | |
|
1671 | 0 | if (sc->state >= SC_ST_CON) { |
1672 | 0 | if (sc_is_conn_error(sc)) |
1673 | 0 | sc->flags |= SC_FL_ERROR; |
1674 | 0 | } |
1675 | | |
1676 | | /* If we had early data, and the handshake ended, then |
1677 | | * we can remove the flag, and attempt to wake the task up, |
1678 | | * in the event there's an analyser waiting for the end of |
1679 | | * the handshake. |
1680 | | */ |
1681 | 0 | if (!(conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS)) && |
1682 | 0 | sc_ep_test(sc, SE_FL_WAIT_FOR_HS)) { |
1683 | 0 | sc_ep_clr(sc, SE_FL_WAIT_FOR_HS); |
1684 | 0 | task_wakeup(sc_strm_task(sc), TASK_WOKEN_MSG); |
1685 | 0 | } |
1686 | |
|
1687 | 0 | if (!sc_state_in(sc->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO) && |
1688 | 0 | (conn->flags & CO_FL_WAIT_XPRT) == 0) { |
1689 | 0 | if (sc->flags & SC_FL_ISBACK) |
1690 | 0 | __sc_strm(sc)->conn_exp = TICK_ETERNITY; |
1691 | 0 | oc->flags |= CF_WRITE_EVENT; |
1692 | 0 | if (sc->state == SC_ST_CON) |
1693 | 0 | sc->state = SC_ST_RDY; |
1694 | 0 | } |
1695 | | |
1696 | | /* Report EOI on the channel if it was reached from the mux point of |
1697 | | * view. |
1698 | | * |
1699 | | * Note: This test is only required because sc_conn_process is also the SI |
1700 | | * wake callback. Otherwise sc_conn_recv()/sc_conn_send() already take |
1701 | | * care of it. |
1702 | | */ |
1703 | 0 | if (sc_ep_test(sc, SE_FL_EOI) && !(sc->flags & SC_FL_EOI)) { |
1704 | 0 | sc->flags |= SC_FL_EOI; |
1705 | 0 | ic->flags |= CF_READ_EVENT; |
1706 | 0 | sc_ep_report_read_activity(sc); |
1707 | 0 | } |
1708 | | |
1709 | | /* Report EOS on the channel if it was reached from the mux point of |
1710 | | * view. |
1711 | | * |
1712 | | * Note: This test is only required because sc_conn_process is also the SI |
1713 | | * wake callback. Otherwise sc_conn_recv()/sc_conn_send() already take |
1714 | | * care of it. |
1715 | | */ |
1716 | 0 | if (sc_ep_test(sc, SE_FL_EOS) && !(sc->flags & SC_FL_EOS)) { |
1717 | | /* we received a shutdown */ |
1718 | 0 | if (ic->flags & CF_AUTO_CLOSE) |
1719 | 0 | sc_schedule_shutdown(sc_opposite(sc)); |
1720 | 0 | sc_conn_eos(sc); |
1721 | 0 | } |
1722 | |
|
1723 | 0 | if (sc_ep_test(sc, SE_FL_ERROR) && !(sc->flags & SC_FL_ERROR)) { |
1724 | 0 | if (!(sc->flags & SC_FL_EOS)) |
1725 | 0 | sc_report_term_evt(sc, (sc->flags & SC_FL_EOI ? strm_tevt_type_rcv_err: strm_tevt_type_truncated_rcv_err)); |
1726 | 0 | sc->flags |= SC_FL_ERROR; |
1727 | 0 | } |
1728 | | |
1729 | | /* Second step : update the stream connector and channels, try to forward any |
1730 | | * pending data, then possibly wake the stream up based on the new |
1731 | | * stream connector status. |
1732 | | */ |
1733 | 0 | sc_notify(sc); |
1734 | 0 | stream_release_buffers(__sc_strm(sc)); |
1735 | 0 | return 0; |
1736 | 0 | } |
1737 | | |
1738 | | /* This is the ->process() function for any stream connector's wait_event task. |
1739 | | * It's assigned during the stream connector's initialization, for any type of |
1740 | | * stream connector. Thus it is always safe to perform a tasklet_wakeup() on a |
1741 | | * stream connector, as the presence of the SC is checked there. |
1742 | | */ |
1743 | | struct task *sc_conn_io_cb(struct task *t, void *ctx, unsigned int state) |
1744 | 0 | { |
1745 | 0 | struct stconn *sc = ctx; |
1746 | 0 | int ret = 0; |
1747 | |
|
1748 | 0 | if (!sc_conn(sc)) |
1749 | 0 | return t; |
1750 | | |
1751 | 0 | if (!(sc->wait_event.events & SUB_RETRY_SEND) && (co_data(sc_oc(sc)) || sc_ep_have_ff_data(sc) || (sc->sedesc->iobuf.flags & IOBUF_FL_FF_BLOCKED))) |
1752 | 0 | ret = sc_conn_send(sc); |
1753 | 0 | if (!(sc->wait_event.events & SUB_RETRY_RECV)) |
1754 | 0 | ret |= sc_conn_recv(sc); |
1755 | 0 | if (ret != 0 || (state & TASK_WOKEN_MSG)) |
1756 | 0 | sc_conn_process(sc); |
1757 | |
|
1758 | 0 | stream_release_buffers(__sc_strm(sc)); |
1759 | 0 | return t; |
1760 | 0 | } |
1761 | | |
1762 | | /* |
1763 | | * This function propagates an end-of-stream received from an applet. It |
1764 | | * updates the stream connector. If it is is already shut, the applet is |
1765 | | * released. Otherwise, we try to forward the shutdown, immediately or ASAP. |
1766 | | */ |
1767 | | static void sc_applet_eos(struct stconn *sc) |
1768 | 0 | { |
1769 | 0 | struct channel *ic = sc_ic(sc); |
1770 | |
|
1771 | 0 | BUG_ON(!sc_appctx(sc)); |
1772 | |
|
1773 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
1774 | 0 | return; |
1775 | 0 | sc->flags |= SC_FL_EOS; |
1776 | 0 | ic->flags |= CF_READ_EVENT; |
1777 | 0 | sc_ep_report_read_activity(sc); |
1778 | 0 | sc_report_term_evt(sc, (sc->flags & SC_FL_EOI ? strm_tevt_type_eos: strm_tevt_type_truncated_eos)); |
1779 | | |
1780 | | /* Note: on abort, we don't call the applet */ |
1781 | |
|
1782 | 0 | if (sc->state != SC_ST_EST) |
1783 | 0 | return; |
1784 | | |
1785 | 0 | if (sc->flags & SC_FL_SHUT_DONE) { |
1786 | 0 | se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_NORMAL); |
1787 | 0 | sc->state = SC_ST_DIS; |
1788 | 0 | if (sc->flags & SC_FL_ISBACK) |
1789 | 0 | __sc_strm(sc)->conn_exp = TICK_ETERNITY; |
1790 | 0 | } |
1791 | 0 | else if (sc_cond_forward_shut(sc)) |
1792 | 0 | return sc_shutdown(sc); |
1793 | 0 | } |
1794 | | |
1795 | | /* |
1796 | | * This is the callback which is called by the applet layer to receive data into |
1797 | | * the buffer from the appctx. It iterates over the applet's rcv_buf |
1798 | | * function. Please do not statify this function, it's often present in |
1799 | | * backtraces, it's useful to recognize it. |
1800 | | */ |
1801 | | int sc_applet_recv(struct stconn *sc) |
1802 | 0 | { |
1803 | 0 | struct appctx *appctx = __sc_appctx(sc); |
1804 | 0 | struct channel *ic = sc_ic(sc); |
1805 | 0 | int ret, max, cur_read = 0; |
1806 | 0 | int read_poll = MAX_READ_POLL_LOOPS; |
1807 | 0 | int flags = 0; |
1808 | | |
1809 | | |
1810 | | /* If another call to sc_applet_recv() failed, give up now. |
1811 | | */ |
1812 | 0 | if (sc_waiting_room(sc)) |
1813 | 0 | return 0; |
1814 | | |
1815 | | /* maybe we were called immediately after an asynchronous abort */ |
1816 | 0 | if (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) |
1817 | 0 | return 1; |
1818 | | |
1819 | | /* We must wait because the applet is not fully initialized */ |
1820 | 0 | if (se_fl_test(sc->sedesc, SE_FL_ORPHAN)) |
1821 | 0 | return 0; |
1822 | | |
1823 | | /* stop immediately on errors. */ |
1824 | 0 | if (!sc_ep_test(sc, SE_FL_RCV_MORE)) { |
1825 | | // TODO: be sure SE_FL_RCV_MORE may be set for applet ? |
1826 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
1827 | 0 | goto end_recv; |
1828 | 0 | } |
1829 | | |
1830 | | /* prepare to detect if the mux needs more room */ |
1831 | 0 | sc_ep_clr(sc, SE_FL_WANT_ROOM); |
1832 | |
|
1833 | 0 | channel_check_idletimer(ic); |
1834 | | |
1835 | | /* First, let's see if we may fast-forward data from a side to the other |
1836 | | * one without using the channel buffer. |
1837 | | */ |
1838 | 0 | if (sc_is_fastfwd_supported(sc)) { |
1839 | 0 | if (channel_data(ic)) { |
1840 | | /* We're embarrassed, there are already data pending in |
1841 | | * the buffer and we don't want to have them at two |
1842 | | * locations at a time. Let's indicate we need some |
1843 | | * place and ask the consumer to hurry. |
1844 | | */ |
1845 | 0 | flags |= CO_RFL_BUF_FLUSH; |
1846 | 0 | goto abort_fastfwd; |
1847 | 0 | } |
1848 | 0 | sc_ep_fwd_kip(sc, sc_opposite(sc)); |
1849 | 0 | ret = appctx_fastfwd(sc, ic->to_forward, flags); |
1850 | 0 | if (ret < 0) |
1851 | 0 | goto abort_fastfwd; |
1852 | 0 | else if (ret > 0) { |
1853 | 0 | if (ic->to_forward != CHN_INFINITE_FORWARD) |
1854 | 0 | ic->to_forward -= ret; |
1855 | 0 | sc->bytes_in += ret; |
1856 | 0 | cur_read += ret; |
1857 | 0 | ic->flags |= CF_READ_EVENT; |
1858 | 0 | } |
1859 | | |
1860 | 0 | if (sc_ep_test(sc, SE_FL_EOS | SE_FL_ERROR)) |
1861 | 0 | goto end_recv; |
1862 | | |
1863 | 0 | if (sc_ep_test(sc, SE_FL_WANT_ROOM)) |
1864 | 0 | sc_need_room(sc, -1); |
1865 | |
|
1866 | 0 | if (sc_ep_test(sc, SE_FL_MAY_FASTFWD_PROD) && ic->to_forward) |
1867 | 0 | goto done_recv; |
1868 | 0 | } |
1869 | | |
1870 | 0 | abort_fastfwd: |
1871 | 0 | if (!sc_alloc_ibuf(sc, &appctx->buffer_wait)) |
1872 | 0 | goto end_recv; |
1873 | | |
1874 | | /* For an HTX stream, if the buffer is stuck (no output data with some |
1875 | | * input data) and if the HTX message is fragmented or if its free space |
1876 | | * wraps, we force an HTX deframentation. It is a way to have a |
1877 | | * contiguous free space nad to let the mux to copy as much data as |
1878 | | * possible. |
1879 | | * |
1880 | | * NOTE: A possible optim may be to let the mux decides if defrag is |
1881 | | * required or not, depending on amount of data to be xferred. |
1882 | | */ |
1883 | 0 | if (IS_HTX_STRM(__sc_strm(sc)) && !co_data(ic)) { |
1884 | 0 | struct htx *htx = htxbuf(&ic->buf); |
1885 | |
|
1886 | 0 | if (htx_is_not_empty(htx) && ((htx->flags & HTX_FL_FRAGMENTED) || htx_space_wraps(htx))) |
1887 | 0 | htx_defrag(htx, NULL, 0); |
1888 | 0 | } |
1889 | | |
1890 | | /* Compute transient CO_RFL_* flags */ |
1891 | 0 | if (co_data(ic)) { |
1892 | 0 | flags |= (CO_RFL_BUF_WET | CO_RFL_BUF_NOT_STUCK); |
1893 | 0 | } |
1894 | | |
1895 | | /* <max> may be null. This is the mux responsibility to set |
1896 | | * SE_FL_RCV_MORE on the SC if more space is needed. |
1897 | | */ |
1898 | 0 | max = channel_recv_max(ic); |
1899 | 0 | if (b_is_small(sc_ib(sc)) || ((ic->flags & CF_WROTE_DATA) && b_is_large(sc_ib(sc)))) |
1900 | 0 | max = 0; |
1901 | 0 | ret = appctx_rcv_buf(sc, &ic->buf, max, flags); |
1902 | 0 | if (sc_ep_test(sc, SE_FL_WANT_ROOM)) { |
1903 | | /* SE_FL_WANT_ROOM must not be reported if the channel's |
1904 | | * buffer is empty. |
1905 | | */ |
1906 | 0 | BUG_ON(c_empty(ic)); |
1907 | |
|
1908 | 0 | sc_need_room(sc, channel_recv_max(ic) + 1); |
1909 | | /* Add READ_PARTIAL because some data are pending but |
1910 | | * cannot be xferred to the channel |
1911 | | */ |
1912 | 0 | ic->flags |= CF_READ_EVENT; |
1913 | 0 | sc_ep_report_read_activity(sc); |
1914 | 0 | } |
1915 | |
|
1916 | 0 | if (ret <= 0) { |
1917 | | /* if we refrained from reading because we asked for a flush to |
1918 | | * satisfy rcv_pipe(), report that there's not enough room here |
1919 | | * to proceed. |
1920 | | */ |
1921 | 0 | if (flags & CO_RFL_BUF_FLUSH) |
1922 | 0 | sc_need_room(sc, -1); |
1923 | 0 | goto done_recv; |
1924 | 0 | } |
1925 | | |
1926 | 0 | cur_read += ret; |
1927 | | |
1928 | | /* if we're allowed to directly forward data, we must update ->o */ |
1929 | 0 | if (ic->to_forward && !(sc_opposite(sc)->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))) { |
1930 | 0 | unsigned long fwd = ret; |
1931 | 0 | if (ic->to_forward != CHN_INFINITE_FORWARD) { |
1932 | 0 | if (fwd > ic->to_forward) |
1933 | 0 | fwd = ic->to_forward; |
1934 | 0 | ic->to_forward -= fwd; |
1935 | 0 | } |
1936 | 0 | c_adv(ic, fwd); |
1937 | 0 | } |
1938 | |
|
1939 | 0 | ic->flags |= CF_READ_EVENT; |
1940 | 0 | sc->bytes_in += ret; |
1941 | | |
1942 | | /* End-of-input reached, we can leave. In this case, it is |
1943 | | * important to break the loop to not block the SC because of |
1944 | | * the channel's policies.This way, we are still able to receive |
1945 | | * shutdowns. |
1946 | | */ |
1947 | 0 | if (sc_ep_test(sc, SE_FL_EOI)) |
1948 | 0 | goto done_recv; |
1949 | | |
1950 | 0 | if ((sc->flags & SC_FL_RCV_ONCE) || --read_poll <= 0) { |
1951 | | /* we don't expect to read more data */ |
1952 | 0 | sc_wont_read(sc); |
1953 | 0 | goto done_recv; |
1954 | 0 | } |
1955 | | |
1956 | | /* if too many bytes were missing from last read, it means that |
1957 | | * it's pointless trying to read again because the system does |
1958 | | * not have them in buffers. |
1959 | | */ |
1960 | 0 | if (ret < max) { |
1961 | | /* if a streamer has read few data, it may be because we |
1962 | | * have exhausted system buffers. It's not worth trying |
1963 | | * again. |
1964 | | */ |
1965 | 0 | if (ic->flags & CF_STREAMER) { |
1966 | | /* we're stopped by the channel's policy */ |
1967 | 0 | sc_wont_read(sc); |
1968 | 0 | goto done_recv; |
1969 | 0 | } |
1970 | | |
1971 | | /* if we read a large block smaller than what we requested, |
1972 | | * it's almost certain we'll never get anything more. |
1973 | | */ |
1974 | 0 | if (ret >= global.tune.recv_enough) { |
1975 | | /* we're stopped by the channel's policy */ |
1976 | 0 | sc_wont_read(sc); |
1977 | 0 | } |
1978 | 0 | } |
1979 | | |
1980 | 0 | done_recv: |
1981 | 0 | if (cur_read) { |
1982 | 0 | channel_check_xfer(ic, cur_read); |
1983 | 0 | sc_ep_report_read_activity(sc); |
1984 | 0 | } |
1985 | |
|
1986 | 0 | end_recv: |
1987 | 0 | ret = (cur_read != 0); |
1988 | | |
1989 | | /* Report EOI on the channel if it was reached from the mux point of |
1990 | | * view. */ |
1991 | 0 | if (sc_ep_test(sc, SE_FL_EOI) && !(sc->flags & SC_FL_EOI)) { |
1992 | 0 | sc_ep_report_read_activity(sc); |
1993 | 0 | sc->flags |= SC_FL_EOI; |
1994 | 0 | ic->flags |= CF_READ_EVENT; |
1995 | 0 | ret = 1; |
1996 | 0 | } |
1997 | |
|
1998 | 0 | if (sc_ep_test(sc, SE_FL_EOS)) { |
1999 | | /* we received a shutdown */ |
2000 | 0 | if (ic->flags & CF_AUTO_CLOSE) |
2001 | 0 | sc_schedule_shutdown(sc_opposite(sc)); |
2002 | 0 | sc_applet_eos(sc); |
2003 | 0 | ret = 1; |
2004 | 0 | } |
2005 | |
|
2006 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) { |
2007 | 0 | sc->flags |= SC_FL_ERROR; |
2008 | 0 | ret = 1; |
2009 | 0 | } |
2010 | 0 | else if (cur_read || (sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM))) { |
2011 | 0 | se_have_more_data(sc->sedesc); |
2012 | 0 | ret = 1; |
2013 | 0 | } |
2014 | |
|
2015 | 0 | return ret; |
2016 | 0 | } |
2017 | | |
2018 | | /* This tries to perform a synchronous receive on the stream connector to |
2019 | | * try to collect last arrived data. In practice it's only implemented on |
2020 | | * stconns. Returns 0 if nothing was done, non-zero if new data or a |
2021 | | * shutdown were collected. This may result on some delayed receive calls |
2022 | | * to be programmed and performed later, though it doesn't provide any |
2023 | | * such guarantee. |
2024 | | */ |
2025 | | int sc_applet_sync_recv(struct stconn *sc) |
2026 | 0 | { |
2027 | 0 | if (!appctx_app_test(__sc_appctx(sc), APPLET_FL_NEW_API)) |
2028 | 0 | return 0; |
2029 | | |
2030 | 0 | if (sc_ep_test(sc, SE_FL_APPLET_NEED_CONN) && |
2031 | 0 | sc_state_in(sc_opposite(sc)->state, SC_SB_RDY|SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) { |
2032 | 0 | sc_ep_clr(sc, SE_FL_APPLET_NEED_CONN); |
2033 | 0 | sc_ep_report_read_activity(sc); |
2034 | 0 | } |
2035 | |
|
2036 | 0 | if (!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST)) |
2037 | 0 | return 0; |
2038 | | |
2039 | 0 | if (se_fl_test(sc->sedesc, SE_FL_ORPHAN)) |
2040 | 0 | return 0; |
2041 | | |
2042 | 0 | if (!sc_is_recv_allowed(sc)) |
2043 | 0 | return 0; // already failed |
2044 | | |
2045 | 0 | return sc_applet_recv(sc); |
2046 | 0 | } |
2047 | | |
2048 | | /* |
2049 | | * This function is called to send buffer data to an applet. It calls the |
2050 | | * applet's snd_buf function. Please do not statify this function, it's often |
2051 | | * present in backtraces, it's useful to recognize it. |
2052 | | */ |
2053 | | int sc_applet_send(struct stconn *sc) |
2054 | 0 | { |
2055 | 0 | struct stconn *sco = sc_opposite(sc); |
2056 | 0 | struct channel *oc = sc_oc(sc); |
2057 | 0 | size_t ret; |
2058 | 0 | int did_send = 0; |
2059 | |
|
2060 | 0 | if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING)) { |
2061 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); |
2062 | 0 | if (co_data(oc)) |
2063 | 0 | sc_ep_report_blocked_send(sc, 0); |
2064 | 0 | return 1; |
2065 | 0 | } |
2066 | | |
2067 | 0 | if (sc_ep_test(sc, SE_FL_WONT_CONSUME)) |
2068 | 0 | return 0; |
2069 | | |
2070 | | /* we might have been called just after an asynchronous shutw */ |
2071 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
2072 | 0 | return 1; |
2073 | | |
2074 | | /* We must wait because the applet is not fully initialized */ |
2075 | 0 | if (se_fl_test(sc->sedesc, SE_FL_ORPHAN)) |
2076 | 0 | return 0; |
2077 | | |
2078 | 0 | sc_ep_fwd_kip(sco, sc); |
2079 | | |
2080 | | /* TODO: Splicing is not supported, so it is not possible to have FF data stuck into the I/O buf */ |
2081 | 0 | BUG_ON(sc_ep_have_ff_data(sc)); |
2082 | |
|
2083 | 0 | if (co_data(oc)) { |
2084 | 0 | unsigned int send_flag = 0; |
2085 | |
|
2086 | 0 | if ((sc->flags & SC_FL_SHUT_WANTED) && co_data(oc) == c_data(oc)) |
2087 | 0 | send_flag |= CO_SFL_LAST_DATA; |
2088 | |
|
2089 | 0 | ret = appctx_snd_buf(sc, &oc->buf, co_data(oc), send_flag); |
2090 | 0 | if (ret > 0) { |
2091 | 0 | did_send = 1; |
2092 | 0 | c_rew(oc, ret); |
2093 | 0 | c_realign_if_empty(oc); |
2094 | 0 | sc->bytes_out += ret; |
2095 | 0 | if (!co_data(oc)) { |
2096 | | /* Always clear both flags once everything has been sent, they're one-shot */ |
2097 | 0 | sc->flags &= ~(SC_FL_SND_ASAP|SC_FL_SND_EXP_MORE); |
2098 | 0 | } |
2099 | | /* if some data remain in the buffer, it's only because the |
2100 | | * system buffers are full, we will try next time. |
2101 | | */ |
2102 | 0 | } |
2103 | 0 | } |
2104 | |
|
2105 | 0 | if (did_send) |
2106 | 0 | oc->flags |= CF_WRITE_EVENT | CF_WROTE_DATA; |
2107 | |
|
2108 | 0 | if (!sco->room_needed || (did_send && (sco->room_needed < 0 || channel_recv_max(sc_oc(sc)) >= sco->room_needed))) |
2109 | 0 | sc_have_room(sco); |
2110 | |
|
2111 | 0 | if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING)) { |
2112 | 0 | oc->flags |= CF_WRITE_EVENT; |
2113 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); |
2114 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
2115 | 0 | sc->flags |= SC_FL_ERROR; |
2116 | 0 | return 1; |
2117 | 0 | } |
2118 | | |
2119 | 0 | if (!co_data(oc)) { |
2120 | 0 | if (did_send) |
2121 | 0 | sc_ep_report_send_activity(sc); |
2122 | 0 | } |
2123 | 0 | else { |
2124 | 0 | sc_ep_report_blocked_send(sc, did_send); |
2125 | 0 | } |
2126 | |
|
2127 | 0 | return did_send; |
2128 | 0 | } |
2129 | | |
2130 | | void sc_applet_sync_send(struct stconn *sc) |
2131 | 0 | { |
2132 | 0 | struct channel *oc = sc_oc(sc); |
2133 | |
|
2134 | 0 | oc->flags &= ~CF_WRITE_EVENT; |
2135 | |
|
2136 | 0 | if (!appctx_app_test(__sc_appctx(sc), APPLET_FL_NEW_API)) |
2137 | 0 | return; |
2138 | | |
2139 | 0 | if (sc->flags & SC_FL_SHUT_DONE) |
2140 | 0 | return; |
2141 | | |
2142 | 0 | if (!co_data(oc)) |
2143 | 0 | return; |
2144 | | |
2145 | 0 | if (!sc_state_in(sc->state, SC_SB_EST)) |
2146 | 0 | return; |
2147 | | |
2148 | 0 | if (se_fl_test(sc->sedesc, SE_FL_ORPHAN)) |
2149 | 0 | return; |
2150 | | |
2151 | 0 | sc_applet_send(sc); |
2152 | 0 | if (oc->flags & CF_WRITE_EVENT) |
2153 | 0 | oc->flags |= CF_WAKE_ONCE; |
2154 | 0 | } |
2155 | | |
2156 | | /* Callback to be used by applet handlers upon completion. It updates the stream |
2157 | | * (which may or may not take this opportunity to try to forward data), then |
2158 | | * may re-enable the applet's based on the channels and stream connector's final |
2159 | | * states. Please do not statify this function, it's often present in backtraces, |
2160 | | * it's useful to recognize it. |
2161 | | */ |
2162 | | int sc_applet_process(struct stconn *sc) |
2163 | 0 | { |
2164 | 0 | struct channel *ic = sc_ic(sc); |
2165 | |
|
2166 | 0 | BUG_ON(!sc_appctx(sc)); |
2167 | | |
2168 | | /* Report EOI on the channel if it was reached from the applet point of |
2169 | | * view. */ |
2170 | 0 | if (sc_ep_test(sc, SE_FL_EOI) && !(sc->flags & SC_FL_EOI)) { |
2171 | 0 | sc_ep_report_read_activity(sc); |
2172 | 0 | sc->flags |= SC_FL_EOI; |
2173 | 0 | ic->flags |= CF_READ_EVENT; |
2174 | 0 | } |
2175 | |
|
2176 | 0 | if (sc_ep_test(sc, SE_FL_ERROR)) |
2177 | 0 | sc->flags |= SC_FL_ERROR; |
2178 | |
|
2179 | 0 | if (sc_ep_test(sc, SE_FL_EOS)) { |
2180 | | /* we received a shutdown */ |
2181 | 0 | sc_applet_eos(sc); |
2182 | 0 | } |
2183 | |
|
2184 | 0 | BUG_ON(sc_ep_test(sc, SE_FL_HAVE_NO_DATA|SE_FL_EOI) == SE_FL_EOI); |
2185 | | |
2186 | | /* If the applet wants to write and the channel is closed, it's a |
2187 | | * broken pipe and it must be reported. |
2188 | | */ |
2189 | 0 | if (!sc_ep_test(sc, SE_FL_HAVE_NO_DATA) && (sc->flags & (SC_FL_EOS|SC_FL_ABRT_DONE))) |
2190 | 0 | sc_ep_set(sc, SE_FL_ERROR); |
2191 | | |
2192 | | /* automatically mark the applet having data available if it reported |
2193 | | * begin blocked by the channel. |
2194 | | */ |
2195 | 0 | if ((sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM)) || |
2196 | 0 | sc_ep_test(sc, SE_FL_APPLET_NEED_CONN)) |
2197 | 0 | applet_have_more_data(__sc_appctx(sc)); |
2198 | | |
2199 | | /* update the stream connector, channels, and possibly wake the stream up */ |
2200 | 0 | sc_notify(sc); |
2201 | 0 | stream_release_buffers(__sc_strm(sc)); |
2202 | | |
2203 | | /* sc_notify may have passed through chk_snd and released some blocking |
2204 | | * flags. Process_stream will consider those flags to wake up the |
2205 | | * appctx but in the case the task is not in runqueue we may have to |
2206 | | * wakeup the appctx immediately. |
2207 | | */ |
2208 | 0 | if ((sc_is_recv_allowed(sc) && !applet_fl_test(__sc_appctx(sc), APPCTX_FL_OUTBLK_ALLOC)) || |
2209 | 0 | (sc_is_send_allowed(sc) && !applet_fl_test(__sc_appctx(sc), APPCTX_FL_INBLK_ALLOC))) |
2210 | 0 | appctx_wakeup(__sc_appctx(sc)); |
2211 | 0 | return 0; |
2212 | 0 | } |
2213 | | |
2214 | | |
2215 | | /* Prepares an endpoint upgrade. We don't now at this stage if the upgrade will |
2216 | | * succeed or not and if the stconn will be reused by the new endpoint. Thus, |
2217 | | * for now, only pretend the stconn is detached. |
2218 | | */ |
2219 | | void sc_conn_prepare_endp_upgrade(struct stconn *sc) |
2220 | 0 | { |
2221 | 0 | BUG_ON(!sc_conn(sc) || !sc->app); |
2222 | 0 | sc_ep_clr(sc, SE_FL_T_MUX); |
2223 | 0 | sc_ep_set(sc, SE_FL_DETACHED); |
2224 | 0 | } |
2225 | | |
2226 | | /* Endpoint upgrade failed. Restore the stconn state. */ |
2227 | | void sc_conn_abort_endp_upgrade(struct stconn *sc) |
2228 | 0 | { |
2229 | 0 | sc_ep_set(sc, SE_FL_T_MUX); |
2230 | 0 | sc_ep_clr(sc, SE_FL_DETACHED); |
2231 | 0 | } |
2232 | | |
2233 | | /* Commit the endpoint upgrade. If stconn is attached, it means the new endpoint |
2234 | | * use it. So we do nothing. Otherwise, the stconn will be destroy with the |
2235 | | * overlying stream. So, it means we must commit the detach. |
2236 | | */ |
2237 | | void sc_conn_commit_endp_upgrade(struct stconn *sc) |
2238 | 0 | { |
2239 | 0 | if (!sc_ep_test(sc, SE_FL_DETACHED)) |
2240 | 0 | return; |
2241 | 0 | sc_detach_endp(&sc); |
2242 | | /* Because it was already set as detached, the sedesc must be preserved */ |
2243 | 0 | BUG_ON(!sc); |
2244 | 0 | BUG_ON(!sc->sedesc); |
2245 | 0 | } |
2246 | | |
2247 | | /* Return a debug string exposing the internals of the front or back |
2248 | | * stream/connection when supported. It will be protocol-dependent and will |
2249 | | * change over time like the output of "show fd" or "show sess all". |
2250 | | */ |
2251 | | static int smp_fetch_debug_str(const struct arg *args, struct sample *smp, const char *kw, void *private) |
2252 | 0 | { |
2253 | 0 | struct connection *conn; |
2254 | 0 | struct stconn *sc; |
2255 | 0 | union mux_sctl_dbg_str_ctx sctl_ctx = { }; |
2256 | |
|
2257 | 0 | if (!smp->strm) |
2258 | 0 | return 0; |
2259 | | |
2260 | 0 | sc = (kw[0] == 'f' ? smp->strm->scf : smp->strm->scb); |
2261 | 0 | conn = sc_conn(sc); |
2262 | |
|
2263 | 0 | if (!conn) |
2264 | 0 | return 0; |
2265 | | |
2266 | | /* a missing mux is necessarily on the backend, and may arrive later */ |
2267 | 0 | if (!conn->mux) { |
2268 | 0 | smp->flags |= SMP_F_MAY_CHANGE; |
2269 | 0 | return 0; |
2270 | 0 | } |
2271 | | |
2272 | | /* Not implemented, return nothing */ |
2273 | 0 | if (!conn->mux->sctl) |
2274 | 0 | return 0; |
2275 | | |
2276 | 0 | sctl_ctx.arg.debug_flags = args->data.sint ? args->data.sint : ~0U; |
2277 | 0 | if (conn->mux->sctl(sc, MUX_SCTL_DBG_STR, &sctl_ctx) == -1) |
2278 | 0 | return 0; |
2279 | | |
2280 | 0 | smp->data.type = SMP_T_STR; |
2281 | 0 | smp->flags = SMP_F_VOL_TEST | SMP_F_MAY_CHANGE; |
2282 | 0 | smp->data.u.str = sctl_ctx.ret.buf; |
2283 | 0 | return 1; |
2284 | 0 | } |
2285 | | |
2286 | | /* return the frontend or backend mux stream ID. |
2287 | | */ |
2288 | | static int |
2289 | | smp_fetch_sid(const struct arg *args, struct sample *smp, const char *kw, void *private) |
2290 | 0 | { |
2291 | 0 | struct connection *conn; |
2292 | 0 | struct stconn *sc; |
2293 | 0 | int64_t sid = 0; |
2294 | |
|
2295 | 0 | if (!smp->strm) |
2296 | 0 | return 0; |
2297 | | |
2298 | 0 | sc = (kw[0] == 'f' ? smp->strm->scf : smp->strm->scb); |
2299 | 0 | conn = sc_conn(sc); |
2300 | | |
2301 | | /* No connection */ |
2302 | 0 | if (!conn) |
2303 | 0 | return 0; |
2304 | | |
2305 | | /* No mux install, this may change */ |
2306 | 0 | if (!conn->mux) { |
2307 | 0 | smp->flags |= SMP_F_MAY_CHANGE; |
2308 | 0 | return 0; |
2309 | 0 | } |
2310 | | |
2311 | | /* No sctl, report sid=0 in this case */ |
2312 | 0 | if (conn->mux->sctl) { |
2313 | 0 | if (conn->mux->sctl(sc, MUX_SCTL_SID, &sid) == -1) |
2314 | 0 | return 0; |
2315 | 0 | } |
2316 | | |
2317 | 0 | smp->flags = SMP_F_VOL_TXN; |
2318 | 0 | smp->data.type = SMP_T_SINT; |
2319 | 0 | smp->data.u.sint = sid; |
2320 | |
|
2321 | 0 | return 1; |
2322 | 0 | } |
2323 | | |
2324 | | /* return 1 if the frontend or backend mux stream has received an abort and 0 otherwise. |
2325 | | */ |
2326 | | static int |
2327 | | smp_fetch_strm_aborted(const struct arg *args, struct sample *smp, const char *kw, void *private) |
2328 | 0 | { |
2329 | 0 | struct stconn *sc; |
2330 | 0 | unsigned int aborted = 0; |
2331 | |
|
2332 | 0 | if (!smp->strm) |
2333 | 0 | return 0; |
2334 | | |
2335 | 0 | sc = (kw[0] == 'f' ? smp->strm->scf : smp->strm->scb); |
2336 | 0 | if (sc->sedesc->abort_info.info) |
2337 | 0 | aborted = 1; |
2338 | |
|
2339 | 0 | smp->flags = SMP_F_VOL_TXN; |
2340 | 0 | smp->data.type = SMP_T_BOOL; |
2341 | 0 | smp->data.u.sint = aborted; |
2342 | |
|
2343 | 0 | return 1; |
2344 | 0 | } |
2345 | | |
2346 | | /* return the H2/QUIC RESET code of the frontend or backend mux stream. Any value |
2347 | | * means an a RST_STREAM was received on H2 and a STOP_SENDING on QUIC. Otherwise the sample fetch fails. |
2348 | | */ |
2349 | | static int |
2350 | | smp_fetch_strm_rst_code(const struct arg *args, struct sample *smp, const char *kw, void *private) |
2351 | 0 | { |
2352 | 0 | struct stconn *sc; |
2353 | 0 | unsigned int source; |
2354 | 0 | unsigned long long code = 0; |
2355 | |
|
2356 | 0 | if (!smp->strm) |
2357 | 0 | return 0; |
2358 | | |
2359 | 0 | sc = (kw[0] == 'f' ? smp->strm->scf : smp->strm->scb); |
2360 | 0 | source = ((sc->sedesc->abort_info.info & SE_ABRT_SRC_MASK) >> SE_ABRT_SRC_SHIFT); |
2361 | 0 | if (source != SE_ABRT_SRC_MUX_H2 && source != SE_ABRT_SRC_MUX_QUIC) { |
2362 | 0 | if (!source) |
2363 | 0 | smp->flags |= SMP_F_MAY_CHANGE; |
2364 | 0 | return 0; |
2365 | 0 | } |
2366 | 0 | code = sc->sedesc->abort_info.code; |
2367 | |
|
2368 | 0 | smp->flags = SMP_F_VOL_TXN; |
2369 | 0 | smp->data.type = SMP_T_SINT; |
2370 | 0 | smp->data.u.sint = code; |
2371 | |
|
2372 | 0 | return 1; |
2373 | 0 | } |
2374 | | |
2375 | | /* Note: must not be declared <const> as its list will be overwritten. |
2376 | | * Note: fetches that may return multiple types should be declared using the |
2377 | | * appropriate pseudo-type. If not available it must be declared as the lowest |
2378 | | * common denominator, the type that can be casted into all other ones. |
2379 | | */ |
2380 | | static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { |
2381 | | { "bs.debug_str", smp_fetch_debug_str, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5SRV }, |
2382 | | { "bs.id", smp_fetch_sid, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV }, |
2383 | | { "bs.aborted", smp_fetch_strm_aborted, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV }, |
2384 | | { "bs.rst_code", smp_fetch_strm_rst_code, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV }, |
2385 | | { "fs.debug_str", smp_fetch_debug_str, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI }, |
2386 | | { "fs.id", smp_fetch_sid, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, |
2387 | | { "fs.aborted", smp_fetch_strm_aborted, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI }, |
2388 | | { "fs.rst_code", smp_fetch_strm_rst_code, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI }, |
2389 | | { /* END */ }, |
2390 | | }}; |
2391 | | |
2392 | | INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords); |