MAJOR: init: automatically set maxconn and/or maxsslconn when possible

If a memory size limit is enforced using "-n" on the command line and
one or both of maxconn / maxsslconn are not set, instead of using the
build-time values, haproxy now computes the number of sessions that can
be allocated depending on a number of parameters among which :

  - global.maxconn (if set)
  - global.maxsslconn (if set)
  - maxzlibmem
  - tune.ssl.cachesize
  - presence of SSL in at least one frontend (bind lines)
  - presence of SSL in at least one backend (server lines)
  - tune.bufsize
  - tune.cookie_len

The purpose is to ensure that not haproxy will not run out of memory
when maxing out all parameters. If neither maxconn nor maxsslconn are
used, it will consider that 100% of the sessions involve SSL on sides
where it's supported. That means that it will typically optimize maxconn
for SSL offloading or SSL bridging on all connections. This generally
means that the simple act of enabling SSL in a frontend or in a backend
will significantly reduce the global maxconn but in exchange of that, it
will guarantee that it will not fail.

All metrics may be enforced using #defines to accomodate variations in
SSL libraries or various allocation sizes.
diff --git a/src/haproxy.c b/src/haproxy.c
index 8a8e5f5..31447bf 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -784,8 +784,136 @@
 		global.pidfile = strdup(cfg_pidfile);
 	}
 
-	if (global.maxconn == 0)
-		global.maxconn = DEFAULT_MAXCONN;
+	/* Now we want to compute the maxconn and possibly maxsslconn values.
+	 * It's a bit tricky. If memmax is not set, maxconn defaults to
+	 * DEFAULT_MAXCONN and maxsslconn defaults to DEFAULT_MAXSSLCONN.
+	 *
+	 * If memmax is set, then it depends on which values are set. If
+	 * maxsslconn is set, we use memmax to determine how many cleartext
+	 * connections may be added, and set maxconn to the sum of the two.
+	 * If maxconn is set and not maxsslconn, maxsslconn is computed from
+	 * the remaining amount of memory between memmax and the cleartext
+	 * connections. If neither are set, then it is considered that all
+	 * connections are SSL-capable, and maxconn is computed based on this,
+	 * then maxsslconn accordingly. We need to know if SSL is used on the
+	 * frontends, backends, or both, because when it's used on both sides,
+	 * we need twice the value for maxsslconn, but we only count the
+	 * handshake once since it is not performed on the two sides at the
+	 * same time (frontend-side is terminated before backend-side begins).
+	 * The SSL stack is supposed to have filled ssl_session_cost and
+	 * ssl_handshake_cost during its initialization.
+	 */
+	if (!global.rlimit_memmax) {
+		if (global.maxconn == 0) {
+			global.maxconn = DEFAULT_MAXCONN;
+			if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
+				fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
+		}
+	}
+#ifdef USE_OPENSSL
+	else if (!global.maxconn && !global.maxsslconn &&
+		 (global.ssl_used_frontend || global.ssl_used_backend)) {
+		/* memmax is set, compute everything automatically. Here we want
+		 * to ensure that all SSL connections will be served. We take
+		 * care of the number of sides where SSL is used, and consider
+		 * the worst case : SSL used on both sides and doing a handshake
+		 * simultaneously. Note that we can't have more than maxconn
+		 * handshakes at a time by definition, so for the worst case of
+		 * two SSL conns per connection, we count a single handshake.
+		 */
+		int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
+		int64_t mem = global.rlimit_memmax * 1048576ULL;
+
+		mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
+		mem -= global.maxzlibmem;
+		mem = mem * MEM_USABLE_RATIO;
+
+		global.maxconn = mem /
+			((SESSION_MAX_COST + 2 * global.tune.bufsize) +    // session + 2 buffers per session
+			 sides * global.ssl_session_max_cost + // SSL buffers, one per side
+			 global.ssl_handshake_max_cost);       // 1 handshake per connection max
+
+		global.maxconn = round_2dig(global.maxconn);
+		global.maxsslconn = sides * global.maxconn;
+		if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
+			fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
+			        global.maxconn, global.maxsslconn);
+	}
+	else if (!global.maxsslconn &&
+		 (global.ssl_used_frontend || global.ssl_used_backend)) {
+		/* memmax and maxconn are known, compute maxsslconn automatically.
+		 * maxsslconn being forced, we don't know how many of it will be
+		 * on each side if both sides are being used. The worst case is
+		 * when all connections use only one SSL instance because
+		 * handshakes may be on two sides at the same time.
+		 */
+		int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
+		int64_t mem = global.rlimit_memmax * 1048576ULL;
+		int64_t sslmem;
+
+		mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
+		mem -= global.maxzlibmem;
+		mem = mem * MEM_USABLE_RATIO;
+
+		sslmem = mem - global.maxconn * (int64_t)(SESSION_MAX_COST + 2 * global.tune.bufsize);
+		global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
+		global.maxsslconn = round_2dig(global.maxsslconn);
+
+		if (sslmem <= 0 || global.maxsslconn < sides) {
+			Alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
+			      "high for the global.memmax value (%d MB). The absolute maximum possible value "
+			      "without SSL is %d, but %d was found and SSL is in use.\n",
+			      global.rlimit_memmax,
+			      (int)(mem / (SESSION_MAX_COST + 2 * global.tune.bufsize)),
+			      global.maxconn);
+			exit(1);
+		}
+
+		if (global.maxsslconn > sides * global.maxconn)
+			global.maxsslconn = sides * global.maxconn;
+
+		if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
+			fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
+	}
+#endif
+	else if (!global.maxconn) {
+		/* memmax and maxsslconn are known/unused, compute maxconn automatically */
+		int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
+		int64_t mem = global.rlimit_memmax * 1048576ULL;
+		int64_t clearmem;
+
+		if (global.ssl_used_frontend || global.ssl_used_backend)
+			mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
+
+		mem -= global.maxzlibmem;
+		mem = mem * MEM_USABLE_RATIO;
+
+		clearmem = mem;
+		if (sides)
+			clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
+
+		global.maxconn = clearmem / (SESSION_MAX_COST + 2 * global.tune.bufsize);
+		global.maxconn = round_2dig(global.maxconn);
+
+		if (clearmem <= 0 || !global.maxconn) {
+			Alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
+			      "high for the global.memmax value (%d MB). The absolute maximum possible value "
+			      "is %d, but %d was found.\n",
+			      global.rlimit_memmax,
+			      (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
+			      global.maxsslconn);
+			exit(1);
+		}
+
+		if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
+			if (sides && global.maxsslconn > sides * global.maxconn) {
+				fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
+				        "to be limited to %d. Better reduce global.maxsslconn to get more "
+				        "room for extra connections.\n", global.maxsslconn, global.maxconn);
+			}
+			fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
+		}
+	}
 
 	if (!global.maxpipes) {
 		/* maxpipes not specified. Count how many frontends and backends