]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http_client: Use the sedesc to report and detect end of processing
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 31 Mar 2023 09:30:32 +0000 (11:30 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 5 Apr 2023 06:57:06 +0000 (08:57 +0200)
Just like for other applets, we now use the SE descriptor instead of the
channel to report error and end-of-stream. Here, the applet is a bit
refactored to handle SE descriptor EOS, EOI and ERROR flags

src/http_client.c

index 40d5ab6c8fa5422bf2ef699c6de289ed21a6768f..29db28f028b77a2382743cfc9f0a23fa6453b3c6 100644 (file)
@@ -700,16 +700,19 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
        uint32_t sz;
        int ret;
 
+       if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW))))
+               goto out;
+
        /* The IO handler could be called after the release, so we need to
         * check if hc is still there to run the IO handler */
        if (!hc)
-               return;
+               goto out;
 
        while (1) {
 
                /* required to stop */
                if (hc->flags & HTTPCLIENT_FA_STOP)
-                       goto end;
+                       goto error;
 
                switch(appctx->st0) {
 
@@ -735,8 +738,9 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                else
                                        appctx->st0 = HTTPCLIENT_S_REQ_BODY;
 
-                               goto more; /* we need to leave the IO handler once we wrote the request */
-                       break;
+                               goto out; /* we need to leave the IO handler once we wrote the request */
+                               break;
+
                        case HTTPCLIENT_S_REQ_BODY:
                                /* call the payload callback */
                                {
@@ -750,7 +754,7 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                                htx = htx_from_buf(&req->buf);
 
                                                if (htx_is_empty(hc_htx))
-                                                       goto more;
+                                                       goto out;
 
                                                if (htx_is_empty(htx)) {
                                                        size_t data = hc_htx->data;
@@ -783,30 +787,31 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
 
                                        htx = htx_from_buf(&req->buf);
                                        if (!htx)
-                                               goto more;
+                                               goto out;
 
                                        /* if the request contains the HTX_FL_EOM, we finished the request part. */
-                                       if (htx->flags & HTX_FL_EOM) {
-                                               se_fl_set(appctx->sedesc, SE_FL_EOI);
+                                       if (htx->flags & HTX_FL_EOM)
                                                appctx->st0 = HTTPCLIENT_S_RES_STLINE;
-                                       }
 
                                        goto process_data; /* we need to leave the IO handler once we wrote the request */
                                }
-                       break;
+                               break;
 
                        case HTTPCLIENT_S_RES_STLINE:
+                               /* Request is finished, report EOI */
+                               se_fl_set(appctx->sedesc, SE_FL_EOI);
+
                                /* copy the start line in the hc structure,then remove the htx block */
                                if (!co_data(res))
-                                       goto more;
+                                       goto out;
                                htx = htxbuf(&res->buf);
                                if (!htx)
-                                       goto more;
+                                       goto out;
                                blk = htx_get_head_blk(htx);
                                if (blk && (htx_get_blk_type(blk) == HTX_BLK_RES_SL))
                                        sl = htx_get_blk_ptr(htx, blk);
                                if (!sl || (!(sl->flags & HTX_SL_F_IS_RESP)))
-                                       goto more;
+                                       goto out;
 
                                /* copy the status line in the httpclient */
                                hc->res.status = sl->info.res.status;
@@ -837,10 +842,10 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                        struct http_hdr hdrs[global.tune.max_http_hdr];
 
                                        if (!co_data(res))
-                                               goto more;
+                                               goto out;
                                        htx = htxbuf(&res->buf);
                                        if (!htx)
-                                               goto more;
+                                               goto out;
 
                                        hdr_num = 0;
                                        blk = htx_get_head_blk(htx);
@@ -869,7 +874,7 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                                /* alloc and copy the headers in the httpclient struct */
                                                hc->res.hdrs = calloc((hdr_num + 1), sizeof(*hc->res.hdrs));
                                                if (!hc->res.hdrs)
-                                                       goto end;
+                                                       goto error;
                                                memcpy(hc->res.hdrs, hdrs, sizeof(struct http_hdr) * (hdr_num + 1));
 
                                                /* caller callback */
@@ -885,7 +890,7 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                                appctx->st0 = HTTPCLIENT_S_RES_BODY;
                                        }
                                }
-                       break;
+                               break;
 
                        case HTTPCLIENT_S_RES_BODY:
                                /*
@@ -893,14 +898,14 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
                                 * push them in the hc->res.buf buffer in a raw format.
                                 */
                                if (!co_data(res))
-                                       goto more;
+                                       goto out;
 
                                htx = htxbuf(&res->buf);
                                if (!htx || htx_is_empty(htx))
-                                       goto more;
+                                       goto out;
 
                                if (!b_alloc(&hc->res.buf))
-                                       goto more;
+                                       goto out;
 
                                if (b_full(&hc->res.buf))
                                        goto process_data;
@@ -952,47 +957,35 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
 
                                /* if not finished, should be called again */
                                if (!(htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)))
-                                       goto more;
+                                       goto out;
 
 
                                /* end of message, we should quit */
                                appctx->st0 = HTTPCLIENT_S_RES_END;
-                       break;
+                               break;
 
                        case HTTPCLIENT_S_RES_END:
-                               goto end;
-                       break;
+                               se_fl_set(appctx->sedesc, SE_FL_EOS);
+                               goto out;
+                               break;
                }
        }
 
-process_data:
+out:
+       return;
 
+process_data:
        sc_will_read(sc);
+       goto out;
 
-       return;
 full:
        /* There was not enough room in the response channel */
        sc_need_room(sc);
+       goto out;
 
-more:
-       /* we'll automatically be called again on missing data */
-       if (appctx->st0 == HTTPCLIENT_S_RES_END)
-               goto end;
-
-       /* The state machine tries to handle as much data as possible, if there
-        * isn't any data to handle and a shutdown is detected, let's stop
-        * everything */
-       if ((req->flags & (CF_SHUTR|CF_SHUTR_NOW)) ||
-           (res->flags & CF_SHUTW) ||
-           ((res->flags & CF_SHUTW_NOW) && channel_is_empty(res))) {
-               goto end;
-       }
-       return;
-
-end:
-       sc_shutw(sc);
-       sc_shutr(sc);
-       return;
+error:
+       se_fl_set(appctx->sedesc, SE_FL_ERROR);
+       goto out;
 }
 
 static int httpclient_applet_init(struct appctx *appctx)