./ct_report/coverage/mongoose_c2s_ranch.COVER.html

1 -module(mongoose_c2s_ranch).
2 -behaviour(mongoose_c2s_socket).
3
4 -export([socket_new/2,
5 socket_peername/1,
6 tcp_to_tls/2,
7 socket_handle_data/2,
8 socket_activate/1,
9 socket_close/1,
10 socket_send_xml/2,
11 get_peer_certificate/2,
12 has_peer_cert/2,
13 is_channel_binding_supported/1,
14 get_tls_last_message/1,
15 is_ssl/1]).
16
17 -record(state, {
18 transport :: transport(),
19 ranch_ref :: ranch:ref(),
20 socket :: ranch_transport:socket(),
21 ip :: {inet:ip_address(), inet:port_number()}
22 }).
23
24 -type state() :: #state{}.
25 -type transport() :: ranch_tcp | just_tls | fast_tls.
26
27 -spec socket_new(term(), mongoose_listener:options()) -> state().
28 socket_new({ranch_tcp, RanchRef}, #{proxy_protocol := true}) ->
29
:-(
{ok, #{src_address := PeerIp, src_port := PeerPort}} = ranch:recv_proxy_header(RanchRef, 1000),
30
:-(
{ok, TcpSocket} = ranch:handshake(RanchRef),
31
:-(
#state{
32 transport = ranch_tcp,
33 ranch_ref = RanchRef,
34 socket = TcpSocket,
35 ip = {PeerIp, PeerPort}};
36 socket_new({ranch_tcp, RanchRef}, #{proxy_protocol := false}) ->
37 637 {ok, TcpSocket} = ranch:handshake(RanchRef),
38 637 {ok, Ip} = ranch_tcp:peername(TcpSocket),
39 637 #state{
40 transport = ranch_tcp,
41 ranch_ref = RanchRef,
42 socket = TcpSocket,
43 ip = Ip}.
44
45 -spec socket_peername(state()) -> {inet:ip_address(), inet:port_number()}.
46 socket_peername(#state{ip = Ip}) ->
47 1274 Ip.
48
49 -spec tcp_to_tls(state(), mongoose_listener:options()) ->
50 {ok, state()} | {error, term()}.
51 tcp_to_tls(#state{socket = TcpSocket} = State, #{tls := #{module := TlsMod} = TlsConfig}) ->
52
:-(
case tcp_to_tls(TlsMod, TcpSocket, TlsConfig) of
53 {ok, TlsSocket} ->
54
:-(
{ok, State#state{transport = TlsMod, socket = TlsSocket}};
55 {error, Reason} ->
56
:-(
{error, Reason}
57 end.
58
59 tcp_to_tls(fast_tls, TcpSocket, TlsConfig) ->
60
:-(
PreparedOpts = mongoose_tls:prepare_options(fast_tls, maps:remove(module, TlsConfig)),
61
:-(
ranch_tcp:setopts(TcpSocket, [{active, false}]),
62
:-(
case fast_tls:tcp_to_tls(TcpSocket, PreparedOpts) of
63 {ok, TlsSocket} ->
64
:-(
fast_tls:recv_data(TlsSocket, <<>>),
65
:-(
{ok, TlsSocket};
66
:-(
Other -> Other
67 end;
68 tcp_to_tls(just_tls, TcpSocket, TlsConfig) ->
69
:-(
case just_tls:tcp_to_tls(TcpSocket, TlsConfig) of
70
:-(
{ok, TlsSocket} -> {ok, TlsSocket};
71
:-(
Other -> Other
72 end.
73
74 -spec socket_handle_data(state(), {tcp | ssl, term(), iodata()}) ->
75 iodata() | {raw, [exml:element()]} | {error, term()}.
76 socket_handle_data(#state{transport = fast_tls, socket = TlsSocket}, {tcp, _, Data}) ->
77
:-(
case fast_tls:recv_data(TlsSocket, Data) of
78 {ok, DecryptedData} ->
79
:-(
DataSize = byte_size(DecryptedData),
80
:-(
mongoose_metrics:update(global, [data, xmpp, received, c2s, tls], DataSize),
81
:-(
DecryptedData;
82 {error, Reason} ->
83
:-(
{error, Reason}
84 end;
85 socket_handle_data(#state{transport = just_tls}, {ssl, _, Data}) ->
86
:-(
mongoose_metrics:update(global, [data, xmpp, received, c2s, tls], byte_size(Data)),
87
:-(
Data;
88 socket_handle_data(#state{transport = ranch_tcp, socket = Socket}, {tcp, Socket, Data}) ->
89 5474 mongoose_metrics:update(global, [data, xmpp, received, c2s, tcp], byte_size(Data)),
90 5474 Data.
91
92 -spec socket_activate(state()) -> ok.
93 socket_activate(#state{transport = fast_tls, socket = Socket}) ->
94
:-(
fast_tls:setopts(Socket, [{active, once}]);
95 socket_activate(#state{transport = just_tls, socket = Socket}) ->
96
:-(
just_tls:setopts(Socket, [{active, once}]);
97 socket_activate(#state{transport = ranch_tcp, socket = Socket}) ->
98 6111 ranch_tcp:setopts(Socket, [{active, once}]).
99
100 -spec socket_close(state()) -> ok.
101 socket_close(#state{transport = fast_tls, socket = Socket}) ->
102
:-(
fast_tls:close(Socket);
103 socket_close(#state{transport = just_tls, socket = Socket}) ->
104
:-(
just_tls:close(Socket);
105 socket_close(#state{transport = ranch_tcp, socket = Socket}) ->
106 637 ranch_tcp:close(Socket).
107
108 -spec socket_send_xml(state(), iodata() | exml_stream:element() | [exml_stream:element()]) ->
109 ok | {error, term()}.
110 socket_send_xml(#state{transport = Transport, socket = Socket}, XML) ->
111 8670 Text = exml:to_iolist(XML),
112 8670 case send(Transport, Socket, Text) of
113 ok ->
114 8670 ok;
115 Error ->
116
:-(
Error
117 end.
118
119 -spec send(transport(), ranch_transport:socket(), iodata()) -> ok | {error, term()}.
120 send(fast_tls, Socket, Data) ->
121
:-(
mongoose_metrics:update(global, [data, xmpp, sent, c2s, tls], iolist_size(Data)),
122
:-(
fast_tls:send(Socket, Data);
123 send(just_tls, Socket, Data) ->
124
:-(
mongoose_metrics:update(global, [data, xmpp, sent, c2s, tls], iolist_size(Data)),
125
:-(
just_tls:send(Socket, Data);
126 send(ranch_tcp, Socket, Data) ->
127 8670 mongoose_metrics:update(global, [data, xmpp, sent, c2s, tcp], iolist_size(Data)),
128 8670 ranch_tcp:send(Socket, Data).
129
130 -spec get_peer_certificate(state(), mongoose_listener:options()) ->
131 mongoose_c2s_socket:peercert_return().
132 get_peer_certificate(#state{transport = fast_tls, socket = Socket}, #{tls := TlsOpts}) ->
133
:-(
case {fast_tls:get_verify_result(Socket), fast_tls:get_peer_certificate(Socket), TlsOpts} of
134
:-(
{0, {ok, Cert}, _} -> {ok, Cert};
135 %% 18 is OpenSSL's and fast_tls's error code for self-signed certs
136
:-(
{18, {ok, Cert}, #{verify_mode := selfsigned_peer}} -> {ok, Cert};
137
:-(
{Error, {ok, Cert}, _} -> {bad_cert, fast_tls:get_cert_verify_string(Error, Cert)};
138
:-(
{_, error, _} -> no_peer_cert
139 end;
140 get_peer_certificate(#state{transport = just_tls, socket = Socket}, _) ->
141
:-(
just_tls:get_peer_certificate(Socket);
142 get_peer_certificate(#state{transport = ranch_tcp}, _) ->
143
:-(
no_peer_cert.
144
145 -spec has_peer_cert(state(), mongoose_listener:options()) -> boolean().
146 has_peer_cert(State, LOpts) ->
147
:-(
case get_peer_certificate(State, LOpts) of
148
:-(
{ok, _} -> true;
149
:-(
_ -> false
150 end.
151
152 -spec is_channel_binding_supported(state()) -> boolean().
153 is_channel_binding_supported(#state{transport = Transport}) ->
154 1274 fast_tls == Transport.
155
156 -spec get_tls_last_message(state()) -> {ok, binary()} | {error, term()}.
157 get_tls_last_message(#state{transport = fast_tls, socket = Socket}) ->
158
:-(
fast_tls:get_tls_last_message(peer, Socket);
159 get_tls_last_message(_) ->
160
:-(
{error, undefined}.
161
162 -spec is_ssl(state()) -> boolean().
163 is_ssl(#state{transport = Transport}) ->
164 1911 ranch_tcp /= Transport.
Line Hits Source