Merge SSLv23_method and DTLS_ANY_VERSION.

This makes SSLv23_method go through DTLS_ANY_VERSION's version negotiation
logic. This allows us to get rid of duplicate ClientHello logic. For
compatibility, SSL_METHOD is now split into SSL_PROTOCOL_METHOD and a version.
The legacy version-locked methods set min_version and max_version based this
version field to emulate the original semantics.

As a bonus, we can now handle fragmented ClientHello versions now.

Because SSLv23_method is a silly name, deprecate that too and introduce
TLS_method.

Change-Id: I8b3df2b427ae34c44ecf972f466ad64dc3dbb171
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
index 2bf4dd2..2ab1cf7 100644
--- a/ssl/s3_meth.c
+++ b/ssl/s3_meth.c
@@ -54,54 +54,119 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
-
 #include "ssl_locl.h"
 
 
-IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_method)
+static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
+    ssl3_new,
+    ssl3_clear,
+    ssl3_free,
+    ssl3_accept,
+    ssl3_connect,
+    ssl3_read,
+    ssl3_peek,
+    ssl3_write,
+    ssl3_shutdown,
+    ssl3_renegotiate,
+    ssl3_renegotiate_check,
+    ssl3_get_message,
+    ssl3_read_bytes,
+    ssl3_write_bytes,
+    ssl3_dispatch_alert,
+    ssl3_ctrl,
+    ssl3_ctx_ctrl,
+    ssl3_pending,
+    ssl3_num_ciphers,
+    ssl3_get_cipher,
+    ssl_undefined_void_function,
+    ssl3_callback_ctrl,
+    ssl3_ctx_callback_ctrl,
+};
 
-IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method)
+const SSL_METHOD *TLS_method(void) {
+  static const SSL_METHOD method = {
+      0,
+      &TLS_protocol_method,
+  };
+  return &method;
+}
 
-IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method)
+const SSL_METHOD *SSLv23_method(void) {
+  return TLS_method();
+}
 
-IMPLEMENT_tls_meth_func(SSL3_VERSION, SSLv3_method)
+/* Legacy version-locked methods. */
 
-const SSL_METHOD *TLSv1_2_server_method(void)
-	{
-	return TLSv1_2_method();
-	}
+const SSL_METHOD *TLSv1_2_method(void) {
+  static const SSL_METHOD method = {
+      TLS1_2_VERSION,
+      &TLS_protocol_method,
+  };
+  return &method;
+}
 
-const SSL_METHOD *TLSv1_1_server_method(void)
-	{
-	return TLSv1_1_method();
-	}
+const SSL_METHOD *TLSv1_1_method(void) {
+  static const SSL_METHOD method = {
+      TLS1_1_VERSION,
+      &TLS_protocol_method,
+  };
+  return &method;
+}
 
-const SSL_METHOD *TLSv1_server_method(void)
-	{
-	return TLSv1_method();
-	}
+const SSL_METHOD *TLSv1_method(void) {
+  static const SSL_METHOD method = {
+      TLS1_VERSION,
+      &TLS_protocol_method,
+  };
+  return &method;
+}
 
-const SSL_METHOD *SSLv3_server_method(void)
-	{
-	return SSLv3_method();
-	}
+const SSL_METHOD *SSLv3_method(void) {
+  static const SSL_METHOD method = {
+      SSL3_VERSION,
+      &TLS_protocol_method,
+  };
+  return &method;
+}
 
-const SSL_METHOD *TLSv1_2_client_method(void)
-	{
-	return TLSv1_2_method();
-	}
+/* Legacy side-specific methods. */
 
-const SSL_METHOD *TLSv1_1_client_method(void)
-	{
-	return TLSv1_1_method();
-	}
+const SSL_METHOD *TLSv1_2_server_method(void) {
+  return TLSv1_2_method();
+}
 
-const SSL_METHOD *TLSv1_client_method(void)
-	{
-	return TLSv1_method();
-	}
+const SSL_METHOD *TLSv1_1_server_method(void) {
+  return TLSv1_1_method();
+}
 
-const SSL_METHOD *SSLv3_client_method(void)
-	{
-	return SSLv3_method();
-	}
+const SSL_METHOD *TLSv1_server_method(void) {
+  return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_server_method(void) {
+  return SSLv3_method();
+}
+
+const SSL_METHOD *TLSv1_2_client_method(void) {
+  return TLSv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_1_client_method(void) {
+  return TLSv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_client_method(void) {
+  return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_client_method(void) {
+  return SSLv3_method();
+}
+
+const SSL_METHOD *SSLv23_server_method(void) {
+  return SSLv23_method();
+}
+
+const SSL_METHOD *SSLv23_client_method(void) {
+  return SSLv23_method();
+}