./ct_report/coverage/mongoose_c2s_socket.COVER.html

1 -module(mongoose_c2s_socket).
2
3 -include_lib("public_key/include/public_key.hrl").
4 -include("mongoose_logger.hrl").
5
6 -export([new/3,
7 handle_data/2,
8 activate/1,
9 close/1,
10 is_channel_binding_supported/1,
11 get_tls_last_message/1,
12 get_peer_certificate/2,
13 has_peer_cert/2,
14 tcp_to_tls/2,
15 is_ssl/1,
16 send_xml/2]).
17
18 -export([get_ip/1,
19 get_transport/1,
20 get_conn_type/1]).
21
22 -callback socket_new(term(), mongoose_c2s:listener_opts()) -> state().
23 -callback socket_peername(state()) -> {inet:ip_address(), inet:port_number()}.
24 -callback tcp_to_tls(state(), mongoose_c2s:listener_opts()) ->
25 {ok, state()} | {error, term()}.
26 -callback socket_handle_data(state(), {tcp | ssl, term(), iodata()}) ->
27 iodata() | {raw, [exml:element()]} | {error, term()}.
28 -callback socket_activate(state()) -> ok.
29 -callback socket_close(state()) -> ok.
30 -callback socket_send_xml(state(), iodata() | exml_stream:element() | [exml_stream:element()]) ->
31 ok | {error, term()}.
32 -callback get_peer_certificate(state(), mongoose_c2s:listener_opts()) -> peercert_return().
33 -callback has_peer_cert(state(), mongoose_c2s:listener_opts()) -> boolean().
34 -callback is_channel_binding_supported(state()) -> boolean().
35 -callback get_tls_last_message(state()) -> {ok, binary()} | {error, term()}.
36 -callback is_ssl(state()) -> boolean().
37
38 -record(c2s_socket, {module :: module(),
39 state :: state()}).
40 -type socket() :: #c2s_socket{}.
41 -type state() :: term().
42 -type conn_type() :: c2s | c2s_tls.
43 -type peercert_return() :: no_peer_cert | {bad_cert, term()} | {ok, #'Certificate'{}}.
44 -export_type([socket/0, state/0, conn_type/0, peercert_return/0]).
45
46 -spec new(module(), term(), mongoose_listener:options()) -> socket().
47 new(Module, SocketOpts, LOpts) ->
48 7771 State = Module:socket_new(SocketOpts, LOpts),
49 7770 PeerIp = Module:socket_peername(State),
50 7770 verify_ip_is_not_blacklisted(PeerIp),
51 7770 C2SSocket = #c2s_socket{
52 module = Module,
53 state = State},
54 7770 handle_socket_and_ssl_config(C2SSocket, LOpts).
55
56 verify_ip_is_not_blacklisted(PeerIp) ->
57 7770 case mongoose_hooks:check_bl_c2s(PeerIp) of
58 true ->
59
:-(
?LOG_INFO(#{what => c2s_blacklisted_ip, ip => PeerIp,
60
:-(
text => <<"Connection attempt from blacklisted IP">>}),
61
:-(
throw({stop, {shutdown, ip_blacklisted}});
62 false ->
63 7770 ok
64 end.
65
66 handle_socket_and_ssl_config(C2SSocket, #{tls := #{mode := tls}} = LOpts) ->
67 827 case tcp_to_tls(C2SSocket, LOpts) of
68 {ok, TlsC2SSocket} ->
69 543 activate(TlsC2SSocket),
70 543 TlsC2SSocket;
71 {error, closed} ->
72
:-(
throw({stop, {shutdown, tls_closed}});
73 {error, timeout} ->
74
:-(
throw({stop, {shutdown, tls_timeout}});
75 {error, {tls_alert, TlsAlert}} ->
76 284 throw({stop, TlsAlert})
77 end;
78 handle_socket_and_ssl_config(C2SSocket, _Opts) ->
79 6943 activate(C2SSocket),
80 6943 C2SSocket.
81
82 -spec tcp_to_tls(socket(), mongoose_listener:options()) -> {ok, socket()} | {error, term()}.
83 tcp_to_tls(#c2s_socket{module = Module, state = State} = C2SSocket, LOpts) ->
84 925 case Module:tcp_to_tls(State, LOpts) of
85 {ok, NewState} ->
86 638 {ok, C2SSocket#c2s_socket{state = NewState}};
87 Error ->
88 287 Error
89 end.
90
91 -spec handle_data(socket(), {tcp | ssl, term(), iodata()}) ->
92 iodata() | {raw, [term()]} | {error, term()}.
93 handle_data(#c2s_socket{module = Module, state = State}, Payload) ->
94 58104 Module:socket_handle_data(State, Payload);
95 handle_data(_, _) ->
96
:-(
{error, bad_packet}.
97
98 -spec activate(socket()) -> ok | {error, term()}.
99 activate(#c2s_socket{module = Module, state = State}) ->
100 65277 Module:socket_activate(State).
101
102 -spec close(socket()) -> ok.
103 close(#c2s_socket{module = Module, state = State}) ->
104 7486 Module:socket_close(State).
105
106 -spec send_xml(socket(), exml_stream:element() | [exml_stream:element()]) -> ok | {error, term()}.
107 send_xml(#c2s_socket{module = Module, state = State}, XML) ->
108 83123 Module:socket_send_xml(State, XML).
109
110 -spec get_peer_certificate(socket(), mongoose_c2s:listener_opts()) -> peercert_return().
111 get_peer_certificate(#c2s_socket{module = Module, state = State}, LOpts) ->
112 66 Module:get_peer_certificate(State, LOpts).
113
114 -spec has_peer_cert(socket(), mongoose_listener:options()) -> boolean().
115 has_peer_cert(#c2s_socket{module = Module, state = State}, LOpts) ->
116 192 Module:has_peer_cert(State, LOpts).
117
118 -spec is_channel_binding_supported(socket()) -> boolean().
119 is_channel_binding_supported(#c2s_socket{module = Module, state = State}) ->
120 15179 Module:is_channel_binding_supported(State).
121
122 -spec is_ssl(socket()) -> boolean().
123 is_ssl(#c2s_socket{module = Module, state = State}) ->
124 20453 Module:is_ssl(State).
125
126 -spec get_transport(socket()) -> module().
127 get_transport(#c2s_socket{module = Module}) ->
128
:-(
Module.
129
130 -spec get_tls_last_message(socket()) -> {ok, binary()} | {error, term()}.
131 get_tls_last_message(#c2s_socket{module = Module, state = State}) ->
132 20 Module:get_tls_last_message(State).
133
134 -spec get_conn_type(socket()) -> conn_type().
135 get_conn_type(Socket) ->
136 6581 case is_ssl(Socket) of
137 74 true -> c2s_tls;
138 6507 false -> c2s
139 end.
140
141 -spec get_ip(socket()) -> term().
142 get_ip(#c2s_socket{module = Module, state = State}) ->
143 6967 Module:socket_peername(State).
Line Hits Source