./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 273 {ok, TcpSocket} = ranch:handshake(RanchRef),
38 273 {ok, Ip} = ranch_tcp:peername(TcpSocket),
39 273 #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 425 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 155 case tcp_to_tls(TlsMod, TcpSocket, TlsConfig) of
53 {ok, TlsSocket} ->
54 155 {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 155 PreparedOpts = mongoose_tls:prepare_options(fast_tls, maps:remove(module, TlsConfig)),
61 155 ranch_tcp:setopts(TcpSocket, [{active, false}]),
62 155 case fast_tls:tcp_to_tls(TcpSocket, PreparedOpts) of
63 {ok, TlsSocket} ->
64 155 fast_tls:recv_data(TlsSocket, <<>>),
65 155 {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 158 case fast_tls:recv_data(TlsSocket, Data) of
78 {ok, DecryptedData} ->
79 4 DataSize = byte_size(DecryptedData),
80 4 mongoose_metrics:update(global, [data, xmpp, received, c2s, tls], DataSize),
81 4 DecryptedData;
82 {error, Reason} ->
83 154 {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 750 mongoose_metrics:update(global, [data, xmpp, received, c2s, tcp], byte_size(Data)),
90 750 Data.
91
92 -spec socket_activate(state()) -> ok.
93 socket_activate(#state{transport = fast_tls, socket = Socket}) ->
94 159 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 868 ranch_tcp:setopts(Socket, [{active, once}]).
99
100 -spec socket_close(state()) -> ok.
101 socket_close(#state{transport = fast_tls, socket = Socket}) ->
102 155 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 118 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 1340 Text = exml:to_iolist(XML),
112 1340 case send(Transport, Socket, Text) of
113 ok ->
114 1334 ok;
115 Error ->
116 6 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 1340 mongoose_metrics:update(global, [data, xmpp, sent, c2s, tcp], iolist_size(Data)),
128 1340 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 1010 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 286 ranch_tcp /= Transport.
Line Hits Source