]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: applet: Add a .shut callback function for applets
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 4 Jul 2024 08:07:59 +0000 (10:07 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jul 2024 13:27:04 +0000 (15:27 +0200)
Applets can now define a shutdown callback function, just like the
multiplexer. It is especially usefull to get the abort reason. This will be
pretty useful to get the status code from the SPOP stream to report it at
the SPOe filter level.

The related issue is #2502.

include/haproxy/applet-t.h
src/stconn.c

index a305da67b8565d1925e854100589ce7a8011b7b9..ced9d15c1cdb152af3365d370c9c43c28bd0001f 100644 (file)
@@ -55,6 +55,7 @@ struct appctx;
 struct proxy;
 struct stconn;
 struct sedesc;
+struct se_abort_info;
 struct session;
 
 /* Applet descriptor */
@@ -68,6 +69,7 @@ struct applet {
        size_t (*rcv_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* called from the upper layer to get data */
        size_t (*snd_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Called from the upper layet to put data */
        size_t (*fastfwd)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Callback to fast-forward data */
+       void (*shut)(struct appctx *appctx, unsigned int mode, struct se_abort_info *reason); /* shutdown function */
        void (*release)(struct appctx *);  /* callback to release resources, may be NULL */
        unsigned int timeout;              /* execution timeout. */
 };
index 607740305aad3fbbf598481758cd00925ba49762..21284dc12f2f9afba01243d6c98cff99c782f33a 100644 (file)
@@ -141,16 +141,15 @@ void sedesc_free(struct sedesc *sedesc)
  */
 void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode)
 {
-       if (se_fl_test(sedesc, SE_FL_T_MUX)) {
-               const struct mux_ops *mux = (sedesc->conn ? sedesc->conn->mux : NULL);
-               unsigned int flags = 0;
-
-               if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(sedesc, SE_FL_SHW))
-                       flags |= (mode & SE_SHW_NORMAL) ? SE_FL_SHWN : SE_FL_SHWS;
+       unsigned int flags = 0;
 
+       if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(sedesc, SE_FL_SHW))
+               flags |= (mode & SE_SHW_NORMAL) ? SE_FL_SHWN : SE_FL_SHWS;
+       if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(sedesc, SE_FL_SHR))
+               flags |= (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR;
 
-               if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(sedesc, SE_FL_SHR))
-                       flags |= (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR;
+       if (se_fl_test(sedesc, SE_FL_T_MUX)) {
+               const struct mux_ops *mux = (sedesc->conn ? sedesc->conn->mux : NULL);
 
                if (flags) {
                        if (mux && mux->shut) {
@@ -165,20 +164,32 @@ void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode)
                                }
 
                                mux->shut(sedesc->sc, mode, reason);
-
                        }
                        se_fl_set(sedesc, flags);
                }
        }
        else if (se_fl_test(sedesc, SE_FL_T_APPLET)) {
-               if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(sedesc, SE_FL_SHW))
-                       se_fl_set(sedesc, SE_FL_SHWN);
+               struct appctx *appctx = sedesc->se;
+
+               if (flags) {
+                       if (appctx->applet->shut) {
+                               struct se_abort_info *reason = NULL;
+                               struct xref *peer = xref_get_peer_and_lock(&sedesc->xref);
 
-               if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(sedesc, SE_FL_SHR))
-                       se_fl_set(sedesc, SE_FL_SHRR);
+                               if (peer) {
+                                       struct sedesc *sdo = container_of(peer, struct sedesc, xref);
+
+                                       reason = &sdo->abort_info;
+                                       xref_unlock(&sedesc->xref, peer);
+                               }
+
+                               appctx->applet->shut(appctx, mode, reason);
+                       }
+                       se_fl_set(sedesc, flags);
+               }
 
                if (se_fl_test(sedesc, SE_FL_SHR) && se_fl_test(sedesc, SE_FL_SHW))
-                       appctx_shut(sedesc->se);
+                       appctx_shut(appctx);
        }
 }