./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 2 {ok, #{src_address := PeerIp, src_port := PeerPort}} = ranch:recv_proxy_header(RanchRef, 1000),
30 1 {ok, TcpSocket} = ranch:handshake(RanchRef),
31 1 #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 7198 {ok, TcpSocket} = ranch:handshake(RanchRef),
38 7198 {ok, Ip} = ranch_tcp:peername(TcpSocket),
39 7198 #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 13446 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 1080 case tcp_to_tls(TlsMod, TcpSocket, TlsConfig) of
53 {ok, TlsSocket} ->
54 639 {ok, State#state{transport = TlsMod, socket = TlsSocket}};
55 {error, Reason} ->
56 441 {error, Reason}
57 end.
58
59 tcp_to_tls(fast_tls, TcpSocket, TlsConfig) ->
60 561 PreparedOpts = mongoose_tls:prepare_options(fast_tls, maps:remove(module, TlsConfig)),
61 561 ranch_tcp:setopts(TcpSocket, [{active, false}]),
62 561 case fast_tls:tcp_to_tls(TcpSocket, PreparedOpts) of
63 {ok, TlsSocket} ->
64 561 fast_tls:recv_data(TlsSocket, <<>>),
65 561 {ok, TlsSocket};
66
:-(
Other -> Other
67 end;
68 tcp_to_tls(just_tls, TcpSocket, TlsConfig) ->
69 519 case just_tls:tcp_to_tls(TcpSocket, TlsConfig) of
70 78 {ok, TlsSocket} -> {ok, TlsSocket};
71 441 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 1366 case fast_tls:recv_data(TlsSocket, Data) of
78 {ok, DecryptedData} ->
79 966 DataSize = byte_size(DecryptedData),
80 966 mongoose_metrics:update(global, [data, xmpp, received, c2s, tls], DataSize),
81 966 DecryptedData;
82 {error, Reason} ->
83 400 {error, Reason}
84 end;
85 socket_handle_data(#state{transport = just_tls}, {ssl, _, Data}) ->
86 211 mongoose_metrics:update(global, [data, xmpp, received, c2s, tls], byte_size(Data)),
87 211 Data;
88 socket_handle_data(#state{transport = ranch_tcp, socket = Socket}, {tcp, Socket, Data}) ->
89 50077 mongoose_metrics:update(global, [data, xmpp, received, c2s, tcp], byte_size(Data)),
90 50077 Data.
91
92 -spec socket_activate(state()) -> ok.
93 socket_activate(#state{transport = fast_tls, socket = Socket}) ->
94 1527 fast_tls:setopts(Socket, [{active, once}]);
95 socket_activate(#state{transport = just_tls, socket = Socket}) ->
96 289 just_tls:setopts(Socket, [{active, once}]);
97 socket_activate(#state{transport = ranch_tcp, socket = Socket}) ->
98 56286 ranch_tcp:setopts(Socket, [{active, once}]).
99
100 -spec socket_close(state()) -> ok.
101 socket_close(#state{transport = fast_tls, socket = Socket}) ->
102 561 fast_tls:close(Socket);
103 socket_close(#state{transport = just_tls, socket = Socket}) ->
104 78 just_tls:close(Socket);
105 socket_close(#state{transport = ranch_tcp, socket = Socket}) ->
106 6122 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 73583 Text = exml:to_iolist(XML),
112 73583 case send(Transport, Socket, Text) of
113 ok ->
114 73406 ok;
115 Error ->
116 177 Error
117 end.
118
119 -spec send(transport(), ranch_transport:socket(), iodata()) -> ok | {error, term()}.
120 send(fast_tls, Socket, Data) ->
121 619 mongoose_metrics:update(global, [data, xmpp, sent, c2s, tls], iolist_size(Data)),
122 619 fast_tls:send(Socket, Data);
123 send(just_tls, Socket, Data) ->
124 263 mongoose_metrics:update(global, [data, xmpp, sent, c2s, tls], iolist_size(Data)),
125 263 just_tls:send(Socket, Data);
126 send(ranch_tcp, Socket, Data) ->
127 72701 mongoose_metrics:update(global, [data, xmpp, sent, c2s, tcp], iolist_size(Data)),
128 72701 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 60 case {fast_tls:get_verify_result(Socket), fast_tls:get_peer_certificate(Socket), TlsOpts} of
134 54 {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 3 {Error, {ok, Cert}, _} -> {bad_cert, fast_tls:get_cert_verify_string(Error, Cert)};
138 3 {_, error, _} -> no_peer_cert
139 end;
140 get_peer_certificate(#state{transport = just_tls, socket = Socket}, _) ->
141 120 just_tls:get_peer_certificate(Socket);
142 get_peer_certificate(#state{transport = ranch_tcp}, _) ->
143 60 no_peer_cert.
144
145 -spec has_peer_cert(state(), mongoose_listener:options()) -> boolean().
146 has_peer_cert(State, LOpts) ->
147 180 case get_peer_certificate(State, LOpts) of
148 110 {ok, _} -> true;
149 70 _ -> false
150 end.
151
152 -spec is_channel_binding_supported(state()) -> boolean().
153 is_channel_binding_supported(#state{transport = Transport}) ->
154 13733 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 20 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 18279 ranch_tcp /= Transport.
Line Hits Source