unsigned int flags; /* other flags */
};
-#define HTTPCLIENT_F_ENDED 0x00000001
+/* Action (FA) to do */
+#define HTTPCLIENT_FA_STOP 0x00000001 /* stops the httpclient at the next IO handler call */
+#define HTTPCLIENT_FA_AUTOKILL 0x00000002 /* sets the applet to destroy the httpclient struct itself */
+
+/* status (FS) */
+#define HTTPCLIENT_FS_ENDED 0x00010000 /* the httpclient is stopped */
/* States of the HTTP Client Appctx */
enum {
#include <haproxy/http_client-t.h>
void httpclient_destroy(struct httpclient *hc);
+void httpclient_stop_and_destroy(struct httpclient *hc);
struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url);
struct appctx *httpclient_start(struct httpclient *hc);
/* Return 1 if the httpclient ended and won't receive any new data */
static inline int httpclient_ended(struct httpclient *hc)
{
- return !!(hc->flags & HTTPCLIENT_F_ENDED);
+ return !!(hc->flags & HTTPCLIENT_FS_ENDED);
}
#endif /* ! _HAPROXY_HTTCLIENT_H */
struct httpclient *hc = appctx->ctx.cli.p0;
/* Everything possible was printed on the CLI, we can destroy the client */
- httpclient_destroy(hc);
+ httpclient_stop_and_destroy(hc);
return;
}
return NULL;
}
+/*
+ * This function tries to destroy the httpclient if it wasn't running.
+ * If it was running, stop the client and ask it to autodestroy itself.
+ *
+ * Once this fonction is used, all pointer sto the client must be removed
+ *
+ */
+void httpclient_stop_and_destroy(struct httpclient *hc)
+{
+
+ /* The httpclient was already stopped, we can safely destroy it */
+ if (hc->flags & HTTPCLIENT_FS_ENDED) {
+ httpclient_destroy(hc);
+ } else {
+ /* if the client wasn't stopped, ask for a stop and destroy */
+ hc->flags |= (HTTPCLIENT_FA_AUTOKILL | HTTPCLIENT_FA_STOP);
+ if (hc->appctx)
+ appctx_wakeup(hc->appctx);
+ }
+}
+
/* Free the httpclient */
void httpclient_destroy(struct httpclient *hc)
{
if (!hc)
return;
+
+ /* we should never destroy a client which was not stopped */
+ BUG_ON(!httpclient_ended(hc));
+
/* request */
istfree(&hc->req.url);
b_free(&hc->req.buf);
while (1) {
+
+ /* required to stop */
+ if (hc->flags & HTTPCLIENT_FA_STOP)
+ goto end;
+
switch(appctx->st0) {
case HTTPCLIENT_S_REQ:
struct httpclient *hc = appctx->ctx.httpclient.ptr;
/* mark the httpclient as ended */
- hc->flags |= HTTPCLIENT_F_ENDED;
+ hc->flags |= HTTPCLIENT_FS_ENDED;
/* the applet is leaving, remove the ptr so we don't try to call it
* again from the caller */
hc->appctx = NULL;
+
+ /* destroy the httpclient when set to autotokill */
+ if (hc->flags & HTTPCLIENT_FA_AUTOKILL) {
+ httpclient_destroy(hc);
+ }
+
return;
}