MEDIUM: session: automatically register the applet designated by the target

Some applet users don't need to initialize their applet, they just want
to route the traffic there just as if it were a server. Since applets
are now connected to from session.c, let's simply ensure that when
connecting, the applet in si->end matches the target, and allocate
one there if it's not already done. In case of error, we force the
status code to resource and connection so that it's clear that it
happens because of a memory shortage.
diff --git a/src/session.c b/src/session.c
index 3122380..1183d91 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1162,6 +1162,29 @@
 
 	if (unlikely(obj_type(s->target) == OBJ_TYPE_APPLET)) {
 		/* the applet directly goes to the EST state */
+		struct appctx *appctx = objt_appctx(si->end);
+
+		if (!appctx || appctx->applet != __objt_applet(s->target))
+			appctx = stream_int_register_handler(si, objt_applet(s->target));
+
+		if (!appctx) {
+			/* No more memory, let's immediately abort. Force the
+			 * error code to ignore the ERR_LOCAL which is not a
+			 * real error.
+			 */
+			s->flags = (s->flags & ~SN_ERR_MASK) | SN_ERR_RESOURCE;
+			s->flags = (s->flags & ~SN_FINST_MASK) | SN_FINST_C;
+
+			si_shutr(si);
+			si_shutw(si);
+			si->ob->flags |= CF_WRITE_ERROR;
+			si->err_type = SI_ET_CONN_OTHER;
+			si->state = SI_ST_CLO;
+			if (s->srv_error)
+				s->srv_error(s, si);
+			return;
+		}
+
 		s->logs.t_queue   = tv_ms_elapsed(&s->logs.tv_accept, &now);
 		s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
 		si->state         = SI_ST_EST;