struct sedesc *sedesc_new();
void sedesc_free(struct sedesc *sedesc);
+void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode);
+
struct stconn *sc_new_from_endp(struct sedesc *sedesc, struct session *sess, struct buffer *input);
struct stconn *sc_new_from_strm(struct stream *strm, unsigned int flags);
struct stconn *sc_new_from_check(struct check *check, unsigned int flags);
return sc->app_ops->name;
}
-static inline void sc_conn_shut(struct stconn *sc, enum se_shut_mode mode)
-{
- const struct mux_ops *mux;
-
- BUG_ON(!sc_conn(sc));
-
- mux = sc_mux_ops(sc);
-
- if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !sc_ep_test(sc, SE_FL_SHW)) {
- if (mux && mux->shutw)
- mux->shutw(sc, mode);
- sc_ep_set(sc, (mode & SE_SHW_NORMAL) ? SE_FL_SHWN : SE_FL_SHWS);
- }
-
- if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !sc_ep_test(sc, SE_FL_SHR)) {
- if (mux && mux->shutr)
- mux->shutr(sc, mode);
- sc_ep_set(sc, (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR);
- }
-}
-
/* Returns non-zero if the stream connector's Rx path is blocked because of
* lack of room in the input buffer. This usually happens after applets failed
* to deliver data into the channel's buffer and reported it via sc_need_room().
/* call the applet's release() function if any, and marks the sedesc as shut
* once both read and write side are shut. Needs to be called upon close().
*/
-void appctx_shut(struct appctx *appctx, enum se_shut_mode mode)
+void appctx_shut(struct appctx *appctx)
{
if (applet_fl_test(appctx, APPCTX_FL_SHUTDOWN))
return;
TRACE_ENTER(APPLET_EV_RELEASE, appctx);
- if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(appctx->sedesc, SE_FL_SHW))
- se_fl_set(appctx->sedesc, SE_FL_SHWN);
- if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(appctx->sedesc, SE_FL_SHR))
- se_fl_set(appctx->sedesc, SE_FL_SHRR);
+ if (appctx->applet->release)
+ appctx->applet->release(appctx);
+ applet_fl_set(appctx, APPCTX_FL_SHUTDOWN);
- if (se_fl_test(appctx->sedesc, SE_FL_SHR) && se_fl_test(appctx->sedesc, SE_FL_SHW)) {
- if (appctx->applet->release)
- appctx->applet->release(appctx);
- applet_fl_set(appctx, APPCTX_FL_SHUTDOWN);
-
- if (LIST_INLIST(&appctx->buffer_wait.list))
- LIST_DEL_INIT(&appctx->buffer_wait.list);
- }
+ if (LIST_INLIST(&appctx->buffer_wait.list))
+ LIST_DEL_INIT(&appctx->buffer_wait.list);
TRACE_LEAVE(APPLET_EV_RELEASE, appctx);
}
}
}
+/* Performs a shutdown on the endpoint. This function deals with connection and
+ * applet endpoints. It is responsible to set SE flags corresponding to the
+ * given shut modes and to call right shutdown functions of the endpoint. It is
+ * called from the .abort and .shut app_ops callback functions at the SC level.
+ */
+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);
+
+ if ((mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) && !se_fl_test(sedesc, SE_FL_SHW)) {
+ if (mux && mux->shutw)
+ mux->shutw(sedesc->sc, mode);
+ se_fl_set(sedesc, (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)) {
+ if (mux && mux->shutr)
+ mux->shutr(sedesc->sc, mode);
+ se_fl_set(sedesc, (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR);
+ }
+ }
+ 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);
+
+ if ((mode & (SE_SHR_RESET|SE_SHR_DRAIN)) && !se_fl_test(sedesc, SE_FL_SHR))
+ se_fl_set(sedesc, SE_FL_SHRR);
+
+ if (se_fl_test(sedesc, SE_FL_SHR) && se_fl_test(sedesc, SE_FL_SHW))
+ appctx_shut(sedesc->se);
+ }
+}
+
/* Tries to allocate a new stconn and initialize its main fields. On
* failure, nothing is allocated and NULL is returned. It is an internal
* function. The caller must, at least, set the SE_FL_ORPHAN or SE_FL_DETACHED
sc_ep_set(sc, SE_FL_ORPHAN);
sc->sedesc->sc = NULL;
sc->sedesc = NULL;
- appctx_shut(appctx, SE_SHR_RESET|SE_SHW_NORMAL);
+ se_shutdown(appctx->sedesc, SE_SHR_RESET|SE_SHW_NORMAL);
appctx_free(appctx);
}
return;
if (sc->flags & SC_FL_SHUT_DONE) {
- sc_conn_shut(sc, SE_SHR_RESET|SE_SHW_SILENT);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT);
sc->state = SC_ST_DIS;
if (sc->flags & SC_FL_ISBACK)
__sc_strm(sc)->conn_exp = TICK_ETERNITY;
* no risk so we close both sides immediately.
*/
if (!(sc->flags & (SC_FL_NOLINGER|SC_FL_EOS|SC_FL_ABRT_DONE)) && !(ic->flags & CF_DONT_READ)) {
- sc_conn_shut(sc, SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHW_NORMAL);
return;
}
- sc_conn_shut(sc, SE_SHR_RESET|((sc->flags & SC_FL_NOLINGER) ? SE_SHW_SILENT : SE_SHW_NORMAL));
+ se_shutdown(sc->sedesc, SE_SHR_RESET|((sc->flags & SC_FL_NOLINGER) ? SE_SHW_SILENT : SE_SHW_NORMAL));
sc->state = SC_ST_DIS;
break;
/* we may have to close a pending connection, and mark the
* response buffer as abort
*/
- sc_conn_shut(sc, SE_SHR_RESET|SE_SHW_SILENT);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT);
sc->state = SC_ST_DIS;
break;
case SC_ST_CER:
return;
if (sc->flags & SC_FL_SHUT_DONE) {
- appctx_shut(__sc_appctx(sc), SE_SHR_RESET|SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_NORMAL);
sc->state = SC_ST_DIS;
if (sc->flags & SC_FL_ISBACK)
__sc_strm(sc)->conn_exp = TICK_ETERNITY;
*/
if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_EOS|SC_FL_ABRT_DONE)) &&
!(ic->flags & CF_DONT_READ)) {
- appctx_shut(__sc_appctx(sc), SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHW_NORMAL);
return;
}
- appctx_shut(__sc_appctx(sc), SE_SHR_RESET|SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_NORMAL);
sc->state = SC_ST_DIS;
break;
case SC_ST_QUE:
case SC_ST_TAR:
/* Note that none of these states may happen with applets */
- appctx_shut(__sc_appctx(sc), SE_SHR_RESET|SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_NORMAL);
sc->state = SC_ST_DIS;
break;
default:
do_close:
/* OK we completely close the socket here just as if we went through sc_shut[rw]() */
- sc_conn_shut(sc, SE_SHR_RESET|SE_SHW_SILENT);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_SILENT);
sc->flags &= ~SC_FL_SHUT_WANTED;
sc->flags |= SC_FL_SHUT_DONE;
return;
if (sc->flags & SC_FL_SHUT_DONE) {
- appctx_shut(__sc_appctx(sc), SE_SHR_RESET|SE_SHW_NORMAL);
+ se_shutdown(sc->sedesc, SE_SHR_RESET|SE_SHW_NORMAL);
sc->state = SC_ST_DIS;
if (sc->flags & SC_FL_ISBACK)
__sc_strm(sc)->conn_exp = TICK_ETERNITY;