Skip to content

Commit 4f519a9

Browse files
authored
Support multple UDP and DTLS ports (#168)
1 parent ef64b6d commit 4f519a9

File tree

3 files changed

+105
-54
lines changed

3 files changed

+105
-54
lines changed

etc/emqx_coap.conf

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22
## CoAP Gateway
33
##--------------------------------------------------------------------
44

5-
## The ip address or interface that CoAP bind with.
5+
## The IP and UDP port that CoAP bind with.
66
##
7-
## Value: IP
8-
## Example:
9-
## coap.ip = 127.0.0.1 | ::1 | 0.0.0.0 | ::
10-
## coap.ip = ::
11-
12-
## The UDP port that CoAP is listening on.
7+
## Default: 0.0.0.0:5683
8+
##
9+
## Examples:
10+
## coap.bind.udp.x = 0.0.0.0:5683 | :::5683 | 127.0.0.1:5683 | ::1:5683
1311
##
14-
## Value: Port
15-
coap.port = 5683
12+
coap.bind.udp.1 = 0.0.0.0:5683
13+
##coap.bind.udp.2 = 0.0.0.0:6683
1614

1715
## Whether to enable statistics for CoAP clients.
1816
##
@@ -25,8 +23,13 @@ coap.enable_stats = off
2523

2624
## The DTLS port that CoAP is listening on.
2725
##
28-
## Value: Port
29-
coap.dtls.port = 5684
26+
## Default: 0.0.0.0:5684
27+
##
28+
## Examples:
29+
## coap.bind.dtls.x = 0.0.0.0:5684 | :::5684 | 127.0.0.1:5684 | ::1:5684
30+
##
31+
coap.bind.dtls.1 = 0.0.0.0:5684
32+
##coap.bind.dtls.2 = 0.0.0.0:6684
3033

3134
## A server only does x509-path validation in mode verify_peer,
3235
## as it then sends a certificate request to the client (this

priv/emqx_coap.schema

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
%%-*- mode: erlang -*-
22
%% emqx_coap config mapping
3-
{mapping, "coap.ip", "emqx_coap.ip", [
4-
{datatype, string}
5-
]}.
6-
7-
{mapping, "coap.port", "emqx_coap.port", [
8-
{datatype, integer}
3+
{mapping, "coap.bind.udp.$number", "emqx_coap.bind_udp", [
4+
{datatype, ip},
5+
{default, "0.0.0.0:5683"}
96
]}.
107

118
{mapping, "coap.enable_stats", "emqx_coap.enable_stats", [
129
{datatype, flag}
1310
]}.
1411

15-
{mapping, "coap.dtls.port", "emqx_coap.dtls_opts", [
16-
{datatype, integer}
12+
{mapping, "coap.bind.dtls.$number", "emqx_coap.bind_dtls", [
13+
{datatype, ip},
14+
{default, "0.0.0.0:5684"}
1715
]}.
1816

1917
{mapping, "coap.dtls.keyfile", "emqx_coap.dtls_opts", [
@@ -41,32 +39,55 @@
4139
{datatype, string}
4240
]}.
4341

42+
{translation, "emqx_coap.bind_udp", fun(Conf) ->
43+
Options = cuttlefish_variable:filter_by_prefix("coap.bind.udp", Conf),
44+
lists:map(fun({_, Bind}) ->
45+
{Ip, Port} = cuttlefish_datatypes:from_string(Bind, ip),
46+
Opts = case inet:parse_address(Ip) of
47+
{ok, {_,_,_,_} = Address} ->
48+
[inet, {ip, Address}];
49+
{ok, {_,_,_,_,_,_,_,_} = Address} ->
50+
[inet6, {ip, Address}]
51+
end,
52+
{Port, Opts}
53+
end, Options)
54+
end}.
55+
56+
{translation, "emqx_coap.bind_dtls", fun(Conf) ->
57+
Options = cuttlefish_variable:filter_by_prefix("coap.bind.dtls", Conf),
58+
lists:map(fun({_, Bind}) ->
59+
{Ip, Port} = cuttlefish_datatypes:from_string(Bind, ip),
60+
Opts = case inet:parse_address(Ip) of
61+
{ok, {_,_,_,_} = Address} ->
62+
[inet, {ip, Address}];
63+
{ok, {_,_,_,_,_,_,_,_} = Address} ->
64+
[inet6, {ip, Address}]
65+
end,
66+
{Port, Opts}
67+
end, Options)
68+
end}.
69+
4470
{translation, "emqx_coap.dtls_opts", fun(Conf) ->
45-
case cuttlefish:conf_get("coap.dtls.port", Conf, undefined) of
46-
undefined -> [];
47-
Port ->
48-
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
71+
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
4972

50-
%% Ciphers
51-
SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
52-
Ciphers =
53-
case cuttlefish:conf_get("coap.dtls.ciphers", Conf, undefined) of
54-
undefined ->
55-
lists:foldl(
56-
fun(TlsVer, Ciphers) ->
57-
Ciphers ++ ssl:cipher_suites(all, TlsVer)
58-
end, [], ['dtlsv1', 'dtlsv1.2']);
59-
C ->
60-
SplitFun(C)
61-
end,
73+
%% Ciphers
74+
SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
75+
Ciphers =
76+
case cuttlefish:conf_get("coap.dtls.ciphers", Conf, undefined) of
77+
undefined ->
78+
lists:foldl(
79+
fun(TlsVer, Ciphers) ->
80+
Ciphers ++ ssl:cipher_suites(all, TlsVer)
81+
end, [], ['dtlsv1', 'dtlsv1.2']);
82+
C ->
83+
SplitFun(C)
84+
end,
6285

63-
Filter([{port, Port},
64-
{verify, cuttlefish:conf_get("coap.dtls.verify", Conf, undefined)},
65-
{keyfile, cuttlefish:conf_get("coap.dtls.keyfile", Conf, undefined)},
66-
{certfile, cuttlefish:conf_get("coap.dtls.certfile", Conf, undefined)},
67-
{cacertfile, cuttlefish:conf_get("coap.dtls.cacertfile", Conf, undefined)},
68-
{fail_if_no_peer_cert, cuttlefish:conf_get("coap.dtls.fail_if_no_peer_cert", Conf, undefined)},
69-
{ciphers, Ciphers}])
70-
end
86+
Filter([{verify, cuttlefish:conf_get("coap.dtls.verify", Conf, undefined)},
87+
{keyfile, cuttlefish:conf_get("coap.dtls.keyfile", Conf, undefined)},
88+
{certfile, cuttlefish:conf_get("coap.dtls.certfile", Conf, undefined)},
89+
{cacertfile, cuttlefish:conf_get("coap.dtls.cacertfile", Conf, undefined)},
90+
{fail_if_no_peer_cert, cuttlefish:conf_get("coap.dtls.fail_if_no_peer_cert", Conf, undefined)},
91+
{ciphers, Ciphers}])
7192
end}.
7293

src/emqx_coap_server.erl

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,47 @@
2424

2525
start() ->
2626
{ok, _} = application:ensure_all_started(gen_coap),
27-
Ip = application:get_env(?APP, ip, undefined),
28-
{ok, _} = coap_server:start_udp(coap_udp_socket, Ip, application:get_env(?APP, port, 5683)),
29-
case application:get_env(?APP, dtls_opts, []) of
30-
[] -> ok;
31-
DtlsOpts ->
32-
DtlsPort = proplists:get_value(port, DtlsOpts),
33-
DtlsOpts1 = proplists:delete(port, DtlsOpts),
34-
{ok, _} = coap_server:start_dtls(coap_dtls_socket, Ip, DtlsPort, DtlsOpts1)
35-
end,
27+
start_udp(),
28+
start_dtls(),
3629
coap_server_registry:add_handler([<<"mqtt">>], emqx_coap_resource, undefined),
3730
coap_server_registry:add_handler([<<"ps">>], emqx_coap_ps_resource, undefined),
3831
emqx_coap_ps_topics:start_link().
3932

4033
stop() ->
41-
_ = coap_server:stop_udp(coap_udp_socket),
42-
_ = coap_server:stop_dtls(coap_dtls_socket).
34+
stop_udp(),
35+
stop_dtls().
36+
37+
start_udp() ->
38+
BindUdps = application:get_env(?APP, bind_udp, [{5683, []}]),
39+
lists:foreach(fun({Port, InetOpt}) ->
40+
Name = process_name(coap_udp_socket, Port),
41+
coap_server:start_udp(Name, Port, InetOpt)
42+
end, BindUdps).
43+
44+
start_dtls() ->
45+
case application:get_env(?APP, dtls_opts, []) of
46+
[] -> ok;
47+
DtlsOpts ->
48+
BindDtls = application:get_env(?APP, bind_dtls, [{5684, []}]),
49+
lists:foreach(fun({DtlsPort, InetOpt}) ->
50+
Name = process_name(coap_dtls_socket, DtlsPort),
51+
coap_server:start_dtls(Name, DtlsPort, InetOpt ++ DtlsOpts)
52+
end, BindDtls)
53+
end.
54+
55+
stop_udp() ->
56+
BindUdps = application:get_env(?APP, bind_udp, [{5683, []}]),
57+
lists:foreach(fun({Port, _}) ->
58+
Name = process_name(coap_udp_socket, Port),
59+
coap_server:stop_udp(Name)
60+
end, BindUdps).
61+
62+
stop_dtls() ->
63+
BindDtls = application:get_env(?APP, bind_dtls, [{5684, []}]),
64+
lists:foreach(fun({Port, _}) ->
65+
Name = process_name(coap_dtls_socket, Port),
66+
coap_server:stop_dtls(Name)
67+
end, BindDtls).
4368

69+
process_name(Mod, Port) ->
70+
list_to_atom(atom_to_list(Mod) ++ "_" ++ integer_to_list(Port)).

0 commit comments

Comments
 (0)