Adapt to OTP28 sslsocket

1. OTP28 changed sslsocket structure
2. an old hack is no longer necessary
This commit is contained in:
Michal Kuratczyk 2025-06-24 18:05:21 +02:00
parent 57b1ec13fd
commit da8f4299b5
No known key found for this signature in database
3 changed files with 9 additions and 38 deletions

View File

@ -610,13 +610,13 @@ ranch_handshake(Ref) ->
tune_buffer_size(Sock, dynamic_buffer) ->
case rabbit_net:setopts(Sock, [{buffer, 128}]) of
ok -> ok;
{error, _} -> rabbit_net:fast_close(Sock),
{error, _} -> _ = rabbit_net:fast_close(Sock),
exit(normal)
end;
tune_buffer_size(Sock, static_buffer) ->
case tune_buffer_size_static(Sock) of
ok -> ok;
{error, _} -> rabbit_net:fast_close(Sock),
{error, _} -> _ = rabbit_net:fast_close(Sock),
exit(normal)
end.

View File

@ -275,7 +275,7 @@ socket_op(Sock, Fun) ->
case Fun(Sock) of
{ok, Res} -> Res;
{error, Reason} -> socket_error(Reason),
rabbit_net:fast_close(RealSocket),
_ = rabbit_net:fast_close(RealSocket),
exit(normal)
end.
@ -287,10 +287,10 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
RealSocket = rabbit_net:unwrap_socket(Sock),
Name = case rabbit_net:connection_string(Sock, inbound) of
{ok, Str} -> list_to_binary(Str);
{error, enotconn} -> rabbit_net:fast_close(RealSocket),
{error, enotconn} -> _ = rabbit_net:fast_close(RealSocket),
exit(normal);
{error, Reason} -> socket_error(Reason),
rabbit_net:fast_close(RealSocket),
_ = rabbit_net:fast_close(RealSocket),
exit(normal)
end,
{ok, HandshakeTimeout} = application:get_env(rabbit, handshake_timeout),
@ -364,7 +364,7 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
%% We don't call gen_tcp:close/1 here since it waits for
%% pending output to be sent, which results in unnecessary
%% delays.
rabbit_net:fast_close(RealSocket),
_ = rabbit_net:fast_close(RealSocket),
rabbit_networking:unregister_connection(self()),
rabbit_core_metrics:connection_closed(self()),
ClientProperties = case get(client_properties) of

View File

@ -82,19 +82,10 @@
-define(SSL_CLOSE_TIMEOUT, 5000).
-define(IS_SSL(Sock), is_tuple(Sock)
andalso (tuple_size(Sock) =:= 3)
andalso (element(1, Sock) =:= sslsocket)).
is_ssl(Sock) -> ?IS_SSL(Sock).
%% Seems hackish. Is hackish. But the structure is stable and
%% kept this way for backward compatibility reasons. We need
%% it for two reasons: there are no ssl:getstat(Sock) function,
%% and no ssl:close(Timeout) function. Both of them are being
%% worked on as we speak.
ssl_get_socket(Sock) ->
element(2, element(2, Sock)).
ssl_info(Sock) when ?IS_SSL(Sock) ->
ssl:connection_information(Sock);
ssl_info(_Sock) ->
@ -119,12 +110,12 @@ controlling_process(Sock, Pid) when is_port(Sock) ->
gen_tcp:controlling_process(Sock, Pid).
getstat(Sock, Stats) when ?IS_SSL(Sock) ->
inet:getstat(ssl_get_socket(Sock), Stats);
ssl:getstat(Sock, Stats);
getstat(Sock, Stats) when is_port(Sock) ->
inet:getstat(Sock, Stats);
%% Used by Proxy protocol support in plugins
getstat({rabbit_proxy_socket, Sock, _}, Stats) when ?IS_SSL(Sock) ->
inet:getstat(ssl_get_socket(Sock), Stats);
ssl:getstat(Sock, Stats);
getstat({rabbit_proxy_socket, Sock, _}, Stats) when is_port(Sock) ->
inet:getstat(Sock, Stats).
@ -177,27 +168,7 @@ close(Sock) when ?IS_SSL(Sock) -> ssl:close(Sock);
close(Sock) when is_port(Sock) -> gen_tcp:close(Sock).
fast_close(Sock) when ?IS_SSL(Sock) ->
%% We cannot simply port_close the underlying tcp socket since the
%% TLS protocol is quite insistent that a proper closing handshake
%% should take place (see RFC 5245 s7.2.1). So we call ssl:close
%% instead, but that can block for a very long time, e.g. when
%% there is lots of pending output and there is tcp backpressure,
%% or the ssl_connection process has entered the the
%% workaround_transport_delivery_problems function during
%% termination, which, inexplicably, does a gen_tcp:recv(Socket,
%% 0), which may never return if the client doesn't send a FIN or
%% that gets swallowed by the network. Since there is no timeout
%% variant of ssl:close, we construct our own.
{Pid, MRef} = spawn_monitor(fun () -> ssl:close(Sock) end),
erlang:send_after(?SSL_CLOSE_TIMEOUT, self(), {Pid, ssl_close_timeout}),
receive
{Pid, ssl_close_timeout} ->
erlang:demonitor(MRef, [flush]),
exit(Pid, kill);
{'DOWN', MRef, process, Pid, _Reason} ->
ok
end,
catch port_close(ssl_get_socket(Sock)),
_ = ssl:close(Sock, ?SSL_CLOSE_TIMEOUT),
ok;
fast_close(Sock) when is_port(Sock) ->
catch port_close(Sock), ok.