-
-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add optional callback ranch_transport:format_error/1
#354
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,8 +89,8 @@ listen_error(Ref, Transport, TransOpts0, Reason, Logger) -> | |
SocketOpts = hide_socket_opts(SocketOpts0), | ||
TransOpts = TransOpts0#{socket_opts => SocketOpts}, | ||
ranch:log(error, | ||
"Failed to start Ranch listener ~p in ~p:listen(~999999p) for reason ~p (~s)~n", | ||
[Ref, Transport, TransOpts, Reason, format_error(Reason)], Logger), | ||
"Failed to start Ranch listener ~p in ~p:listen(~0p) for reason ~p (~s)~n", | ||
[Ref, Transport, TransOpts, Reason, format_error(Transport, Reason)], Logger), | ||
exit({listen_error, Ref, Reason}). | ||
|
||
hide_socket_opts([]) -> | ||
|
@@ -106,9 +106,19 @@ hide_socket_opts([{password, _}|SocketOpts]) -> | |
hide_socket_opts([SocketOpt|SocketOpts]) -> | ||
[SocketOpt|hide_socket_opts(SocketOpts)]. | ||
|
||
format_error(no_cert) -> | ||
%% Handling of no_cert really should be done in ranch_ssl. We leave it here for | ||
%% backwards compatibility with possibly existing custom transports without an | ||
%% format_error/1 implementation that may rely on this module handling it. | ||
%% TODO: Remove in Ranch 3.0 | ||
format_error(_, no_cert) -> | ||
"no certificate provided; see cert, certfile, sni_fun or sni_hosts options"; | ||
format_error(reuseport_local) -> | ||
format_error(_, reuseport_local) -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is generated by |
||
"num_listen_sockets must be set to 1 for local sockets"; | ||
format_error(Reason) -> | ||
inet:format_error(Reason). | ||
format_error(Transport, Reason) -> | ||
%% TODO: Required callback in Ranch 3.0 | ||
case erlang:function_exported(Transport, format_error, 1) of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment saying this will be required in 3.0, and for now let's consider/document it as optional. |
||
true -> | ||
Transport:format_error(Reason); | ||
false -> | ||
lists:flatten(io_lib:format("~0p", [Reason])) | ||
end. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
%% Copyright (c) 2024, Jan Uhlig <[email protected]> | ||
%% | ||
%% Permission to use, copy, modify, and/or distribute this software for any | ||
%% purpose with or without fee is hereby granted, provided that the above | ||
%% copyright notice and this permission notice appear in all copies. | ||
%% | ||
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
|
||
-module(ranch_listen_error_transport). | ||
-behaviour(ranch_transport). | ||
|
||
-export([name/0]). | ||
-export([secure/0]). | ||
-export([messages/0]). | ||
-export([listen/1]). | ||
-export([disallowed_listen_options/0]). | ||
-export([accept/2]). | ||
-export([handshake/2]). | ||
-export([handshake/3]). | ||
-export([handshake_continue/2]). | ||
-export([handshake_continue/3]). | ||
-export([handshake_cancel/1]). | ||
-export([connect/3]). | ||
-export([connect/4]). | ||
-export([recv/3]). | ||
-export([recv_proxy_header/2]). | ||
-export([send/2]). | ||
-export([sendfile/2]). | ||
-export([sendfile/4]). | ||
-export([sendfile/5]). | ||
-export([setopts/2]). | ||
-export([getopts/2]). | ||
-export([getstat/1]). | ||
-export([getstat/2]). | ||
-export([controlling_process/2]). | ||
-export([peername/1]). | ||
-export([sockname/1]). | ||
-export([shutdown/2]). | ||
-export([close/1]). | ||
-export([cleanup/1]). | ||
-export([format_error/1]). | ||
|
||
-type opt() :: ranch_tcp:opt(). | ||
-export_type([opt/0]). | ||
|
||
-type opts() :: ranch_tcp:opts(). | ||
-export_type([opts/0]). | ||
|
||
-spec name() -> tcp. | ||
name() -> tcp. | ||
|
||
-spec secure() -> boolean(). | ||
secure() -> | ||
false. | ||
|
||
-spec messages() -> {tcp, tcp_closed, tcp_error, tcp_passive}. | ||
messages() -> {tcp, tcp_closed, tcp_error, tcp_passive}. | ||
|
||
-spec listen(ranch:transport_opts(opts())) -> {ok, inet:socket()} | {error, atom()}. | ||
listen(_TransOpts) -> | ||
{error, {?MODULE, listen_error}}. | ||
|
||
-spec disallowed_listen_options() -> [atom()]. | ||
disallowed_listen_options() -> | ||
ranch_tcp:disallowed_listen_options(). | ||
|
||
-spec accept(inet:socket(), timeout()) | ||
-> {ok, inet:socket()} | {error, closed | timeout | atom()}. | ||
accept(LSocket, Timeout) -> | ||
ranch_tcp:accept(LSocket, Timeout). | ||
|
||
-spec handshake(inet:socket(), timeout()) -> {ok, inet:socket()}. | ||
handshake(CSocket, Timeout) -> | ||
iranch_tcp:handshake(CSocket, Timeout). | ||
|
||
-spec handshake(inet:socket(), opts(), timeout()) -> {ok, inet:socket()}. | ||
handshake(CSocket, Opts, Timeout) -> | ||
ranch_tcp:handshake(CSocket, Opts, Timeout). | ||
|
||
-spec handshake_continue(inet:socket(), timeout()) -> no_return(). | ||
handshake_continue(CSocket, Timeout) -> | ||
ranch_tcp:handshake_continue(CSocket, Timeout). | ||
|
||
-spec handshake_continue(inet:socket(), opts(), timeout()) -> no_return(). | ||
handshake_continue(CSocket, Opts, Timeout) -> | ||
ranch_tcp:handshake_continue(CSocket, Opts, Timeout). | ||
|
||
-spec handshake_cancel(inet:socket()) -> no_return(). | ||
handshake_cancel(CSocket) -> | ||
ranch_tcp:handshake_cancel(CSocket). | ||
|
||
%% @todo Probably filter Opts? | ||
-spec connect(inet:ip_address() | inet:hostname(), | ||
inet:port_number(), any()) | ||
-> {ok, inet:socket()} | {error, atom()}. | ||
connect(Host, Port, Opts) when is_integer(Port) -> | ||
ranch_tcp:connect(Host, Port, Opts). | ||
|
||
%% @todo Probably filter Opts? | ||
-spec connect(inet:ip_address() | inet:hostname(), | ||
inet:port_number(), any(), timeout()) | ||
-> {ok, inet:socket()} | {error, atom()}. | ||
connect(Host, Port, Opts, Timeout) when is_integer(Port) -> | ||
ranch_tcp:connect(Host, Port, Opts, Timeout). | ||
|
||
-spec recv(inet:socket(), non_neg_integer(), timeout()) | ||
-> {ok, any()} | {error, closed | atom()}. | ||
recv(Socket, Length, Timeout) -> | ||
ranch_tcp:recv(Socket, Length, Timeout). | ||
|
||
-spec recv_proxy_header(inet:socket(), timeout()) | ||
-> {ok, ranch_proxy_header:proxy_info()} | ||
| {error, closed | atom()} | ||
| {error, protocol_error, atom()}. | ||
recv_proxy_header(Socket, Timeout) -> | ||
ranch_tcp:recv_proxy_header(Socket, Timeout). | ||
|
||
-spec send(inet:socket(), iodata()) -> ok | {error, atom()}. | ||
send(Socket, Packet) -> | ||
ranch_tcp:send(Socket, Packet). | ||
|
||
-spec sendfile(inet:socket(), file:name_all() | file:fd()) | ||
-> {ok, non_neg_integer()} | {error, atom()}. | ||
sendfile(Socket, Filename) -> | ||
ranch_tcp:sendfile(Socket, Filename). | ||
|
||
-spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), | ||
non_neg_integer()) | ||
-> {ok, non_neg_integer()} | {error, atom()}. | ||
sendfile(Socket, File, Offset, Bytes) -> | ||
ranch_tcp:sendfile(Socket, File, Offset, Bytes). | ||
|
||
-spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), | ||
non_neg_integer(), [{chunk_size, non_neg_integer()}]) | ||
-> {ok, non_neg_integer()} | {error, atom()}. | ||
sendfile(Socket, Filename, Offset, Bytes, Opts) -> | ||
ranch_tcp:sendfile(Socket, Filename, Offset, Bytes, Opts). | ||
|
||
%% @todo Probably filter Opts? | ||
-spec setopts(inet:socket(), list()) -> ok | {error, atom()}. | ||
setopts(Socket, Opts) -> | ||
ranch_tcp:setopts(Socket, Opts). | ||
|
||
-spec getopts(inet:socket(), [atom()]) -> {ok, list()} | {error, atom()}. | ||
getopts(Socket, Opts) -> | ||
ranch_tcp:getopts(Socket, Opts). | ||
|
||
-spec getstat(inet:socket()) -> {ok, list()} | {error, atom()}. | ||
getstat(Socket) -> | ||
ranch_tcp:getstat(Socket). | ||
|
||
-spec getstat(inet:socket(), [atom()]) -> {ok, list()} | {error, atom()}. | ||
getstat(Socket, OptionNames) -> | ||
ranch_tcp:getstat(Socket, OptionNames). | ||
|
||
-spec controlling_process(inet:socket(), pid()) | ||
-> ok | {error, closed | not_owner | atom()}. | ||
controlling_process(Socket, Pid) -> | ||
ranch_tcp:controlling_process(Socket, Pid). | ||
|
||
-spec peername(inet:socket()) | ||
-> {ok, {inet:ip_address(), inet:port_number()} | {local, binary()}} | {error, atom()}. | ||
peername(Socket) -> | ||
ranch_tcp:peername(Socket). | ||
|
||
-spec sockname(inet:socket()) | ||
-> {ok, {inet:ip_address(), inet:port_number()} | {local, binary()}} | {error, atom()}. | ||
sockname(Socket) -> | ||
ranch_tcp:sockname(Socket). | ||
|
||
-spec shutdown(inet:socket(), read | write | read_write) | ||
-> ok | {error, atom()}. | ||
shutdown(Socket, How) -> | ||
ranch_tcp:shutdown(Socket, How). | ||
|
||
-spec close(inet:socket()) -> ok. | ||
close(Socket) -> | ||
ranch_tcp:close(Socket). | ||
|
||
-spec cleanup(ranch:transport_opts(opts())) -> ok. | ||
cleanup(Opts) -> | ||
ranch_tcp:cleanup(Opts). | ||
|
||
-spec format_error(inet:posix() | system_limit) -> string(). | ||
format_error({?MODULE, Reason}) -> | ||
io_lib:format("There was an error in ~0p: ~0p", [?MODULE, Reason]); | ||
format_error(Reason) -> | ||
ranch_tcp:format_error(Reason). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually belongs in
ranch_ssl:format_error/1
(and is replicated there). For backwards compatibility with existing custom transports without anformat_error
implementation which may rely onranch_acceptors_sup
handling this, I left it in.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Write that in a comment.