Merge pull request #210 from mochi/otp-21.2

Add 21.1 and 21.2.3 to otp_release matrix
diff --git a/.travis.yml b/.travis.yml
index 8de93ab..18bf781 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,8 @@
 notifications:
   email: false
 otp_release:
+  - 21.2.3
+  - 21.1
   - 21.0
   - 20.0
   - 19.0
diff --git a/CHANGES.md b/CHANGES.md
index 7fd273e..e3ac5c3 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,19 @@
+Version 2.19.0 released 2019-01-17
+
+* Fix warning in 21.2.3 and crash on incompatible releases
+  (21.2, 21.2.1, 21.2.2 have a SSL bug)
+  https://github.com/mochi/mochiweb/pull/210
+* Erlang/OTP 21 compatibility
+  https://github.com/mochi/mochiweb/pull/198
+  https://github.com/mochi/mochiweb/pull/204
+* New `{buffer, Buffer}` socket server option
+  https://github.com/mochi/mochiweb/pull/208
+* New `{format, map}` option for mochijson2:decode/2
+  https://github.com/mochi/mochiweb/pull/206
+* No longer crash when a socket is closed server-side
+  https://github.com/mochi/mochiweb/pull/205
+* Support for SameSite cookie setting
+
 Version 2.18.0 released 2018-05-12
 
 * Add the 100.64.0.0/10 private IP shared address range
diff --git a/README b/README
deleted file mode 100644
index 80ee6e4..0000000
--- a/README
+++ /dev/null
@@ -1,17 +0,0 @@
-MochiWeb is an Erlang library for building lightweight HTTP servers.
-
-The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
-
-The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
-
-R12B compatibility:
-The master of MochiWeb is tested with R14A and later. A branch compatible
-with R12B is maintained separately at http://github.com/lemenkov/mochiweb
-The R12B branch of that repository is mirrored in the official repository
-occasionally for convenience.
-
-To create a new mochiweb using project:
-   make app PROJECT=project_name
-
-To create a new mochiweb using project in a specific directory:
-   make app PROJECT=project_name PREFIX=$HOME/projects/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..74e6620
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+MochiWeb is an Erlang library for building lightweight HTTP servers.
+
+The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
+
+The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
+
+To create a new mochiweb using project:
+   make app PROJECT=project_name
+
+To create a new mochiweb using project in a specific directory:
+   make app PROJECT=project_name PREFIX=$HOME/projects/
+
+MochiWeb is currently tested with Erlang/OTP R15B03 through 21.2.3.
+
+# OTP 21.2, 21.2.1, 21.2.2 warning
+
+OTP 21.2 (up to and including 21.2.2) introduced an SSL regression that
+makes these releases unsafe to use. See [ERL-830](https://bugs.erlang.org/browse/ERL-830).
+This issue was resolved in OTP 21.2.3.
diff --git a/rebar.config b/rebar.config
index adc1d78..2fc417e 100644
--- a/rebar.config
+++ b/rebar.config
@@ -4,7 +4,9 @@
             {platform_define, "^(R14|R15|R16B-)", 'crypto_compatibility'},
             {platform_define, "^(R14|R15|R16B|17)", 'rand_mod_unavailable'},
             {platform_define, "^(R14|R15|R16B|17)", 'sni_unavailable'},
-            {platform_define, "^(R14|R15|R16)", 'map_unavailable'}]}.
+            {platform_define, "^(R14|R15|R16)", 'map_unavailable'},
+            {platform_define, "^(R14|R15|R16|17|18|19|20)", 'ssl_handshake_unavailable'},
+            {platform_define, "^21-", 'otp_21'}]}.
 {cover_enabled, true}.
 {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.
 {dialyzer_opts, [{warnings, [no_return,
diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src
index 60f15f5..70c7165 100644
--- a/src/mochiweb.app.src
+++ b/src/mochiweb.app.src
@@ -1,7 +1,7 @@
 %% This is generated from src/mochiweb.app.src
 {application, mochiweb,
  [{description, "MochiMedia Web Server"},
-  {vsn, "2.18.0"},
+  {vsn, "2.19.0"},
   {modules, []},
   {registered, []},
   {env, []},
diff --git a/src/mochiweb_socket.erl b/src/mochiweb_socket.erl
index cbce78a..9aeca2a 100644
--- a/src/mochiweb_socket.erl
+++ b/src/mochiweb_socket.erl
@@ -87,6 +87,7 @@
 transport_accept(ListenSocket) ->
     gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT).
 
+-ifdef(ssl_handshake_unavailable).
 finish_accept({ssl, Socket}) ->
     case ssl:ssl_accept(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
         ok ->
@@ -96,6 +97,17 @@
     end;
 finish_accept(Socket) ->
     {ok, Socket}.
+-else.
+finish_accept({ssl, Socket}) ->
+    case ssl:handshake(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
+        {ok, SslSocket} ->
+            {ok, {ssl, SslSocket}};
+        {error, _} = Err ->
+            Err
+    end;
+finish_accept(Socket) ->
+    {ok, Socket}.
+-endif.
 
 recv({ssl, Socket}, Length, Timeout) ->
     ssl:recv(Socket, Length, Timeout);
diff --git a/src/mochiweb_socket_server.erl b/src/mochiweb_socket_server.erl
index 56c1243..f830483 100644
--- a/src/mochiweb_socket_server.erl
+++ b/src/mochiweb_socket_server.erl
@@ -167,11 +167,26 @@
             gen_server:F(Name, ?MODULE, State, [])
     end.
 
+-ifdef(otp_21).
+check_ssl_compatibility() ->
+    case lists:keyfind(ssl, 1, application:loaded_applications()) of
+        {_, _, V} when V =:= "9.1" orelse V =:= "9.1.1" ->
+            {error, "ssl-" ++ V ++ " (OTP 21.2 to 21.2.2) has a regression and is not safe to use with mochiweb. See https://bugs.erlang.org/browse/ERL-830"};
+        _ ->
+            ok
+    end.
+-else.
+check_ssl_compatibility() ->
+    ok.
+-endif.
+
 prep_ssl(true) ->
     ok = mochiweb:ensure_started(crypto),
     ok = mochiweb:ensure_started(asn1),
     ok = mochiweb:ensure_started(public_key),
-    ok = mochiweb:ensure_started(ssl);
+    ok = mochiweb:ensure_started(ssl),
+    ok = check_ssl_compatibility(),
+    ok;
 prep_ssl(false) ->
     ok.