struct appctx *sc_applet_create(struct stconn *sc, struct applet *app);
+void sc_conn_prepare_endp_upgrade(struct stconn *sc);
+void sc_conn_abort_endp_upgrade(struct stconn *sc);
+void sc_conn_commit_endp_upgrade(struct stconn *sc);
+
/* The se_fl_*() set of functions manipulate the stream endpoint flags from
* the stream endpoint itself. The sc_ep_*() set of functions manipulate the
* stream endpoint flags from the the stream connector (ex. stconn).
appctx_wakeup(__sc_appctx(sc));
return 0;
}
+
+
+/* Prepares an endpoint upgrade. We don't now at this stage if the upgrade will
+ * succeed or not and if the stconn will be reused by the new endpoint. Thus,
+ * for now, only pretend the stconn is detached.
+ */
+void sc_conn_prepare_endp_upgrade(struct stconn *sc)
+{
+ BUG_ON(!sc_conn(sc) || !sc->app);
+ sc_ep_clr(sc, SE_FL_T_MUX);
+ sc_ep_set(sc, SE_FL_DETACHED);
+}
+
+/* Endpoint upgrade failed. Retore the stconn state. */
+void sc_conn_abort_endp_upgrade(struct stconn *sc)
+{
+ sc_ep_set(sc, SE_FL_T_MUX);
+ sc_ep_clr(sc, SE_FL_DETACHED);
+}
+
+/* Commit the endpoint upgrade. If stconn is attached, it means the new endpoint
+ * use it. So we do nothing. Otherwise, the stconn will be destroy with the
+ * overlying stream. So, it means we must commit the detach.
+*/
+void sc_conn_commit_endp_upgrade(struct stconn *sc)
+{
+ if (!sc_ep_test(sc, SE_FL_DETACHED))
+ return;
+ sc_detach_endp(&sc);
+ /* Because it was already set as detached, the sedesc must be preserved */
+ BUG_ON(!sc->sedesc);
+}
if (conn->mux->flags & MX_FL_NO_UPG)
return 0;
+
+ sc_conn_prepare_endp_upgrade(sc);
if (conn_upgrade_mux_fe(conn, sc, &s->req.buf,
(mux_proto ? mux_proto->token : ist("")),
- PROTO_MODE_HTTP) == -1)
+ PROTO_MODE_HTTP) == -1) {
+ sc_conn_abort_endp_upgrade(sc);
return 0;
+ }
+ sc_conn_commit_endp_upgrade(sc);
s->req.flags &= ~(CF_READ_PARTIAL|CF_AUTO_CONNECT);
s->req.total = 0;