si->appctx.applet = applet;
}
+/* returns a pointer to the applet being run in the SI or NULL if none */
+static inline const struct si_applet *si_applet(struct stream_interface *si)
+{
+ return objt_applet(si->conn->target);
+}
+
+/* call the applet's release function if any. Needs to be called upon close() */
+static inline void si_applet_release(struct stream_interface *si)
+{
+ const struct si_applet *applet;
+
+ applet = si_applet(si);
+ if (applet && applet->release)
+ applet->release(si);
+}
+
/* Sends a shutr to the connection using the data layer */
static inline void si_shutr(struct stream_interface *si)
{
struct connection *conn; /* descriptor for a connection */
struct si_ops *ops; /* general operations at the stream interface layer */
- void (*release)(struct stream_interface *); /* handler to call after the last close() */
-
/* struct members below are the "remote" part, as seen from the buffer side */
int conn_retries; /* number of connect retries left */
int send_proxy_ofs; /* <0 = offset to (re)send from the end, >0 = send all */
s->si[0].owner = t;
s->si[0].state = s->si[0].prev_state = SI_ST_EST;
s->si[0].err_type = SI_ET_NONE;
- s->si[0].release = NULL;
s->si[0].send_proxy_ofs = 0;
s->si[0].conn->target = &l->obj_type;
s->si[0].exp = TICK_ETERNITY;
s->si[1].state = s->si[1].prev_state = SI_ST_ASS;
s->si[1].conn_retries = p->conn_retries;
s->si[1].err_type = SI_ET_NONE;
- s->si[1].release = NULL;
s->si[1].send_proxy_ofs = 0;
s->si[1].conn->target = &s->be->obj_type;
si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
s->si[0].owner = t;
s->si[0].state = s->si[0].prev_state = SI_ST_EST;
s->si[0].err_type = SI_ET_NONE;
- s->si[0].release = NULL;
s->si[0].send_proxy_ofs = 0;
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
s->si[1].state = s->si[1].prev_state = SI_ST_INI;
s->si[1].err_type = SI_ET_NONE;
s->si[1].conn_retries = 0; /* used for logging too */
- s->si[1].release = NULL;
s->si[1].send_proxy_ofs = 0;
si_prepare_none(&s->si[1]);
s->si[1].exp = TICK_ETERNITY;
si->conn->flags &= ~CO_FL_XPRT_TRACKED;
conn_full_close(si->conn);
- if (si->release)
- si->release(si);
-
if (si->err_type)
return 0;
if (si->ob->flags & CF_SHUTW) {
si->state = SI_ST_DIS;
si->exp = TICK_ETERNITY;
-
- if (si->release)
- si->release(si);
+ si_applet_release(si);
}
else if (si->flags & SI_FL_NOHALF) {
/* we want to immediately forward this close to the write side */
case SI_ST_TAR:
/* Note that none of these states may happen with applets */
si->state = SI_ST_DIS;
-
- if (si->release)
- si->release(si);
+ si_applet_release(si);
default:
si->flags &= ~(SI_FL_WAIT_ROOM | SI_FL_NOLINGER);
si->ib->flags &= ~CF_SHUTR_NOW;
DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", app, si, si->owner);
si_prepare_applet(si, app);
- si->release = app->release;
si->flags |= SI_FL_WAIT_DATA;
return si->owner;
}
*/
void stream_int_unregister_handler(struct stream_interface *si)
{
- si->release = NULL;
si->owner = NULL;
si->conn->target = NULL;
si->end = NULL;
conn_full_close(conn);
si->state = SI_ST_DIS;
si->exp = TICK_ETERNITY;
-
- if (si->release)
- si->release(si);
}
else if (si->flags & SI_FL_NOHALF) {
/* we want to immediately forward this close to the write side */
case SI_ST_QUE:
case SI_ST_TAR:
si->state = SI_ST_DIS;
-
- if (si->release)
- si->release(si);
+ /* fall through */
default:
si->flags &= ~(SI_FL_WAIT_ROOM | SI_FL_NOLINGER);
si->ib->flags &= ~CF_SHUTR_NOW;
si->state = SI_ST_DIS;
si->exp = TICK_ETERNITY;
- if (si->release)
- si->release(si);
return;
}