From 3cfac3430a0481bdfee640a6d7bb648c3ef8d3b5 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 12 Oct 2016 18:22:20 +0800 Subject: [PATCH] add etc/emqttd.conf, priv/emqttd.schema --- Makefile | 2 + etc/emqttd.conf | 265 +++++++++++++++++++++ priv/emqttd.schema | 556 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 823 insertions(+) create mode 100644 etc/emqttd.conf create mode 100644 priv/emqttd.schema diff --git a/Makefile b/Makefile index 510517428..749a81a0e 100644 --- a/Makefile +++ b/Makefile @@ -37,3 +37,5 @@ include erlang.mk app:: rebar.config +app.config:: + cuttlefish -l info -e etc/ -c etc/emqttd.conf -i priv/emqttd.schema -d data/ diff --git a/etc/emqttd.conf b/etc/emqttd.conf new file mode 100644 index 000000000..28b16d72c --- /dev/null +++ b/etc/emqttd.conf @@ -0,0 +1,265 @@ +##==================================================================== +## +## Configration for EMQ 3.0 +## +##==================================================================== + +##-------------------------------------------------------------------- +## Node +##-------------------------------------------------------------------- + +## Node Id: 1~255 +node.id = 1 + +## Node Name +node.name = emqttd@127.0.0.1 + +## Cookie for distributed node +node.cookie = emq_dist_cookie + +## SMP support: enable, auto, disable +node.smp = auto + +## Enable kernel poll +node.kernel_poll = on + +## async thread pool +node.async_threads = 32 + +## Erlang Process Limit +node.process_limit = 256000 + +## Sets the maximum number of simultaneously existing ports for this system +node.max_ports = 262144 + +## Set the distribution buffer busy limit (dist_buf_busy_limit) +node.dist_buffer_size = 32MB + +## Max ETS Tables. +## Note that mnesia and SSL will create temporary ets tables. +node.max_ets_tables = 256000 + +## Tweak GC to run more often +node.fullsweep_after = 1000 + +## Crash dump +node.crash_dump = $(platform_log_dir)/crash.dump + +##-------------------------------------------------------------------- +## Log +##-------------------------------------------------------------------- + +## Console log. Enum: off, file, console, both +log.console = console + +## Console log level. Enum: debug, info, notice, warning, error, critical, alert, emergency, none +log.console.level = error + +## Console log file +## log.console.file = $(platform_log_dir)/console.log + +## Error log file +log.error.file = $(platform_log_dir)/error.log + +## Enable the crash log. Enum: on, off +log.crash = on + +log.crash.file = $(platform_log_dir)/crash.log + +##-------------------------------------------------------------------- +## MQTT Protocol +##-------------------------------------------------------------------- + +## Max ClientId Length Allowed. +mqtt.max_clientid_len = 1024 + +## Max Packet Size Allowed, 64K by default. +mqtt.max_packet_size = 64KB + +## Client Idle Timeout (Second) +mqtt.client_idle_timeout = 30 + +##-------------------------------------------------------------------- +## MQTT Session +##-------------------------------------------------------------------- + +## Max number of QoS 1 and 2 messages that can be “inflight” at one time. +## 0 means no limit +mqtt.session.max_inflight = 100 + +## Retry interval for redelivering QoS1/2 messages. +mqtt.session.retry_interval = 60 + +## Awaiting PUBREL Timeout +mqtt.session.await_rel_timeout = 20 + +## Max Packets that Awaiting PUBREL, 0 means no limit +mqtt.session.max_awaiting_rel = 0 + +## Statistics Collection Interval(seconds) +mqtt.session.collect_interval = 0 + +## Expired after 2 day: +## w - week +## d - day +## h - hour +## m - minute +## s - second +mqtt.session.expired_after = 2d + +##-------------------------------------------------------------------- +## MQTT Queue +##-------------------------------------------------------------------- + +## Type: simple | priority +mqtt.queue.type = simple + +## Topic Priority: 0~255, Default is 0 +## mqtt.queue.priority = topic/1=10,topic/2=8 + +## Max queue length. Enqueued messages when persistent client disconnected, +## or inflight window is full. +mqtt.queue.max_length = infinity + +## Low-water mark of queued messages +mqtt.queue.low_watermark = 20% + +## High-water mark of queued messages +mqtt.queue.high_watermark = 60% + +## Queue Qos0 messages? +mqtt.queue.qos0 = true + +##-------------------------------------------------------------------- +## MQTT Broker and PubSub +##-------------------------------------------------------------------- + +## System Interval of publishing broker $SYS Messages +mqtt.broker.sys_interval = 60 + +## PubSub Pool Size. Default should be scheduler numbers. +mqtt.pubsub.pool_size = 8 + +mqtt.pubsub.by_clientid = true + +## Subscribe Asynchronously +mqtt.pubsub.async = true + +##-------------------------------------------------------------------- +## MQTT Listeners +##-------------------------------------------------------------------- + +## TCP Listener: 1883, 127.0.0.1:1883, ::1:1883 +mqtt.listener.tcp = 1883 +mqtt.listener.tcp.acceptors = 8 +mqtt.listener.tcp.max_clients = 1024 +## Rate Limit. Format is 'burst,rate', Unit is KB/Sec +## mqtt.listener.tcp.rate_limit = 100,10 +## Mount Point +## mqtt.listener.tcp.mount_point = prefix/ +## TCP Socket Options. Set buffer if hight thoughtput +## mqtt.listener.tcp.opts.recbuf = 4096 +## mqtt.listener.tcp.opts.sndbuf = 4096 +## mqtt.listener.tcp.opts.buffer = 4096 +## mqtt.listener.tcp.opts.nodelay = true +## mqtt.listener.tcp.opts.backlog = 1024 + +## SSL Listener +mqtt.listener.ssl = 8883 +mqtt.listener.ssl.acceptors = 4 +mqtt.listener.ssl.max_clients = 512 +## Rate Limit. Format is 'burst,rate', Unit is KB/Sec +## mqtt.listener.ssl.rate_limit = 100,10 +## Mount Point +## mqtt.listener.ssl.mount_point = prefix/ +## mqtt.listener.ssl.opts.handshake_timeout = 10 ## Seconds +## mqtt.listener.ssl.opts.certfile = $(platform_etc_dir)/ssl/cert.pem +## mqtt.listener.ssl.opts.keyfile = $(platform_etc_dir)/ssl/key.pem +## mqtt.listener.ssl.opts.cacertfile = $(platform_etc_dir)/ssl/cacert.pem +## mqtt.listener.ssl.opts.verify = verify_peer +## mqtt.listener.ssl.opts.failed_if_no_peer_cert = true + +## HTTP Listener +mqtt.listener.http = 127.0.0.1:8083 +mqtt.listener.http.acceptors = 4 +mqtt.listener.http.max_clients = 64 + +## HTTP(SSL) Listener +## mqtt.listener.http = 8083 +## mqtt.listener.http.acceptors = 4 +## mqtt.listener.http.max_clients = 64 + +##-------------------------------------------------------------------- +## MQTT Bridge +##-------------------------------------------------------------------- + +## Bridge Queue Size +mqtt.bridge.max_queue_len = 10000 + +## Ping Interval of bridge node +mqtt.bridge.ping_down_interval = 1 ## Second + +##------------------------------------------------------------------- +## MQTT Plugins +##------------------------------------------------------------------- + +## Dir of plugins' config +mqtt.plugins.etc_dir = $(platform_etc_dir)/plugins/ + +## File to store loaded plugin names. +mqtt.plugins.loaded_file = $(platform_data_dir)/loaded_plugins + +##------------------------------------------------------------------- +## MQTT Modules +##------------------------------------------------------------------- + +## Enable retainer module +## mqtt.module.retainer = on +## disc: disc_copies, ram: ram_copies +## mqtt.module.retainer.storage_type = disc +## Max number of retained messages +## mqtt.module.retainer.max_message_num = 100000 +## Max Payload Size of retained message +## mqtt.module.retainer.max_playload_size = 65536 +## Expired after seconds, never expired if 0 +## mqtt.module.retainer.expired_after = 0 + +## Enable presence module +## Client presence management module. Publish presence messages when +## client connected or disconnected. +## mqtt.module.presence = on +## mqtt.module.presence.qos = 0 + +## Enable subscription module +## Subscribe topics automatically when client connected +## mqtt.module.subscription = on +## mqtt.module.subscription.topics = $client/%c,1;topic2,1 + +## [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite) +## mqtt.module.rewrite = off +## mqtt.module.rewrite.config = etc/modules/rewrite.conf + +##------------------------------------------------------------------- +## System Monitor +##------------------------------------------------------------------- + +## Long GC, don't monitor in production mode for: +## https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 +sysmon.long_gc = false + +## Long Schedule(ms) +sysmon.long_schedule = 240 + +## 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM. +sysmon.large_heap = 8MB + +## Busy Port +sysmon.busy_port = false + +## Busy Dist Port +sysmon.busy_dist_port = true + +platform_etc_dir = ./etc + +platform_log_dir = ./log + diff --git a/priv/emqttd.schema b/priv/emqttd.schema new file mode 100644 index 000000000..b2396348c --- /dev/null +++ b/priv/emqttd.schema @@ -0,0 +1,556 @@ +%%-*- mode: erlang -*- +%% EMQ 3.0 config mapping + +%%-------------------------------------------------------------------- +%% Erlang Node +%%-------------------------------------------------------------------- + +%% @doc Node Id +{mapping, "node.id", "emqttd.node_id", [ + {default, 1}, + {datatype, integer}, + {validators, ["range:0-255"]} +]}. + +%% @doc Erlang node name +{mapping, "node.name", "vm_args.-name", [ + {default, "emqttd@127.0.0.1"} +]}. + +%% @doc Secret cookie for distributed erlang node +{mapping, "node.cookie", "vm_args.-setcookie", [ + {default, "emqsecretcookie"} +]}. + +%% @doc SMP Support +{mapping, "node.smp", "vm_args.-smp", [ + {default, auto}, + {datatype, {enum, [enable, auto, disable]}}, + hidden +]}. + +%% @doc Enable Kernel Poll +{mapping, "node.kernel_poll", "vm_args.+K", [ + {default, on}, + {datatype, flag}, + hidden +]}. + +%% @doc More information at: http://erlang.org/doc/man/erl.html +{mapping, "node.async_threads", "vm_args.+A", [ + {default, 64}, + {datatype, integer}, + {validators, ["range:0-1024"]} +]}. + +%% @doc Erlang Process Limit +{mapping, "node.process_limit", "vm_args.+P", [ + {datatype, integer}, + {default, 256000}, + hidden +]}. + +%% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q +%% @doc The number of concurrent ports/sockets +%% Valid range is 1024-134217727 +{mapping, "node.max_ports", + cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [ + {default, 262144}, + {datatype, integer}, + {validators, ["range4ports"]} +]}. + +{validator, "range4ports", "must be 1024 to 134217727", + fun(X) -> X >= 1024 andalso X =< 134217727 end}. + +%% @doc http://www.erlang.org/doc/man/erl.html#%2bzdbbl +{mapping, "node.dist_buffer_size", "vm_args.+zdbbl", [ + {datatype, bytesize}, + {commented, "32MB"}, + hidden, + {validators, ["zdbbl_range"]} +]}. + +{translation, "vm_args.+zdbbl", + fun(Conf) -> + ZDBBL = cuttlefish:conf_get("node.dist_buffer_size", Conf, undefined), + case ZDBBL of + undefined -> undefined; + X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes; + _ -> undefined + end + end +}. + +{validator, "zdbbl_range", "must be between 1KB and 2097151KB", + fun(ZDBBL) -> + %% 2097151KB = 2147482624 + ZDBBL >= 1024 andalso ZDBBL =< 2147482624 + end +}. + +%% @doc http://www.erlang.org/doc/man/erlang.html#system_flag-2 +{mapping, "node.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [ + {default, 1000}, + {datatype, integer}, + hidden, + {validators, ["positive_integer"]} +]}. + +{validator, "positive_integer", "must be a positive integer", + fun(X) -> X >= 0 end}. + +%% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES, +%% R16+ uses +e +%% @doc The ETS table limit +{mapping, "node.max_ets_tables", + cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [ + {default, 256000}, + {datatype, integer}, + hidden +]}. + +%% @doc Set the location of crash dumps +{mapping, "node.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [ + {default, "{{crash_dump}}"}, + {datatype, file}, + hidden +]}. + +%%-------------------------------------------------------------------- +%% Log +%%-------------------------------------------------------------------- + +{mapping, "log.console", "lager.handlers", [ + {default, file }, + {datatype, {enum, [off, file, console, both]}} +]}. + +{mapping, "log.console.level", "lager.handlers", [ + {default, info}, + {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}} +]}. + +{mapping, "log.console.file", "lager.handlers", [ + {default, "$(platform_log_dir)/console.log"}, + {datatype, file} +]}. + +{mapping, "log.error.file", "lager.handlers", [ + {default, "$(platform_log_dir)/error.log"}, + {datatype, file} +]}. + +{mapping, "log.error.redirect", "lager.error_logger_redirect", [ + {default, on}, + {datatype, flag}, + hidden +]}. + +{mapping, "log.error.messages_per_second", "lager.error_logger_hwm", [ + {default, 1000}, + {datatype, integer}, + hidden +]}. + +{translation, + "lager.handlers", + fun(Conf) -> + ErrorHandler = case cuttlefish:conf_get("log.error.file", Conf) of + undefined -> []; + ErrorFilename -> [{lager_file_backend, [{file, ErrorFilename}, + {level, error}, + {size, 10485760}, + {date, "$D0"}, + {count, 5}]}] + end, + + ConsoleLogLevel = cuttlefish:conf_get("log.console.level", Conf), + ConsoleLogFile = cuttlefish:conf_get("log.console.file", Conf), + + ConsoleHandler = {lager_console_backend, ConsoleLogLevel}, + ConsoleFileHandler = {lager_file_backend, [{file, ConsoleLogFile}, + {level, ConsoleLogLevel}, + {size, 10485760}, + {date, "$D0"}, + {count, 5}]}, + + ConsoleHandlers = case cuttlefish:conf_get("log.console", Conf) of + off -> []; + file -> [ConsoleFileHandler]; + console -> [ConsoleHandler]; + both -> [ConsoleHandler, ConsoleFileHandler]; + _ -> [] + end, + ConsoleHandlers ++ ErrorHandler + end +}. + +{mapping, "log.crash", "lager.crash_log", [ + {default, on}, + {datatype, flag} +]}. + +{mapping, "log.crash.file", "lager.crash_log", [ + {default, "$(platform_log_dir)/crash.log"}, + {datatype, file} +]}. + +{translation, + "lager.crash_log", + fun(Conf) -> + case cuttlefish:conf_get("log.crash", Conf) of + false -> undefined; + _ -> + cuttlefish:conf_get("log.crash.file", Conf, "./log/crash.log") + end + end}. + +{mapping, "sasl", "sasl.sasl_error_logger", [ + {default, off}, + {datatype, flag}, + hidden +]}. + +%%-------------------------------------------------------------------- +%% MQTT Protocol +%%-------------------------------------------------------------------- + +%% @doc Set the Max ClientId Length Allowed. +{mapping, "mqtt.max_clientid_len", "emqttd.protocol", [ + {default, 1024}, + {datatype, integer} +]}. + +%% @doc Max Packet Size Allowed, 64K by default. +{mapping, "mqtt.max_packet_size", "emqttd.protocol", [ + {default, "64KB"}, + {datatype, bytesize} +]}. + +%% @doc Client Idle Timeout. +{mapping, "mqtt.client_idle_timeout", "emqttd.protocol", [ + {default, 30}, + {datatype, integer} +]}. + +{translation, "emqttd.protocol", fun(Conf) -> + [{max_clientid_len, cuttlefish:conf_get("mqtt.max_clientid_len", Conf)}, + {max_packet_size, cuttlefish:conf_get("mqtt.max_packet_size", Conf)}, + {client_idle_timeout, cuttlefish:conf_get("mqtt.client_idle_timeout", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Session +%%-------------------------------------------------------------------- + +%% @doc Max number of QoS 1 and 2 messages that can be “inflight” at one time. +%% 0 means no limit +{mapping, "mqtt.session.max_inflight", "emqttd.session", [ + {default, 100}, + {datatype, integer} +]}. + + +%% @doc Retry interval for redelivering QoS1/2 messages. +{mapping, "mqtt.session.retry_interval", "emqttd.session", [ + {default, 60}, + {datatype, integer} +]}. + +%% @doc Awaiting PUBREL Timeout +{mapping, "mqtt.session.await_rel_timeout", "emqttd.session", [ + {default, 30}, + {datatype, integer} +]}. + +%% @doc Max Packets that Awaiting PUBREL, 0 means no limit +{mapping, "mqtt.session.max_awaiting_rel", "emqttd.session", [ + {default, 0}, + {datatype, integer} +]}. + +%% @doc Statistics Collection Interval(seconds) +{mapping, "mqtt.session.collect_interval", "emqttd.session", [ + {default, 0}, + {datatype, integer} +]}. + +%% @doc Session expired after... +{mapping, "mqtt.session.expired_after", "emqttd.session", [ + {default, "2d"}, + {datatype, {duration, s}} +]}. + +{translation, "emqttd.session", fun(Conf) -> + [{max_inflight, cuttlefish:conf_get("mqtt.session.max_inflight", Conf)}, + {retry_interval, cuttlefish:conf_get("mqtt.session.retry_interval", Conf)}, + {await_rel_timeout, cuttlefish:conf_get("mqtt.session.await_rel_timeout", Conf)}, + {max_awaiting_rel, cuttlefish:conf_get("mqtt.session.max_awaiting_rel", Conf)}, + {collect_interval, cuttlefish:conf_get("mqtt.session.collect_interval", Conf)}, + {expired_after, cuttlefish:conf_get("mqtt.session.expired_after", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Queue +%%-------------------------------------------------------------------- + +%% @doc Type: simple | priority +{mapping, "mqtt.queue.type", "emqttd.queue", [ + {default, simple}, + {datatype, atom} +]}. + +%% @doc Topic Priority: 0~255, Default is 0 +{mapping, "mqtt.queue.priority", "emqttd.queue", [ + {default, ""}, + {datatype, string}, + hidden +]}. + +%% @doc Max queue length. Enqueued messages when persistent client disconnected, or inflight window is full. +{mapping, "mqtt.queue.max_length", "emqttd.queue", [ + {default, infinity}, + {datatype, [atom, integer]} +]}. + +%% @doc Low-water mark of queued messages +{mapping, "mqtt.queue.low_watermark", "emqttd.queue", [ + {default, "20%"}, + {datatype, string}, + hidden +]}. + +%% @doc High-water mark of queued messages +{mapping, "mqtt.queue.high_watermark", "emqttd.queue", [ + {default, "60%"}, + {datatype, string}, + hidden +]}. + +%% @doc Queue Qos0 messages? +{mapping, "mqtt.queue.qos0", "emqttd.queue", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{translation, "emqttd.queue", fun(Conf) -> + Parse = fun(S) -> + {match, [N]} = re:run(S, "^([0-9]+)%$", [{capture, all_but_first, list}]), + list_to_integer(N) / 100 + end, + Opts = [{type, cuttlefish:conf_get("mqtt.queue.type", Conf, simple)}, + {max_length, cuttlefish:conf_get("mqtt.queue.max_length", Conf)}, + {low_watermark, Parse(cuttlefish:conf_get("mqtt.queue.low_watermark", Conf))}, + {high_watermark, Parse(cuttlefish:conf_get("mqtt.queue.high_watermark", Conf))}, + {queue_qos0, cuttlefish:conf_get("mqtt.queue.qos0", Conf)}], + case cuttlefish:conf_get("mqtt.queue.priority", Conf) of + undefined -> Opts; + V -> [{priority, + [begin [T, P] = string:tokens(S, "="), + {T, list_to_integer(P)} + end || S <- string:tokens(V, ",")]}|Opts] + end +end}. + +%%-------------------------------------------------------------------- +%% MQTT Broker +%%-------------------------------------------------------------------- + +{mapping, "mqtt.broker.sys_interval", "emqttd.broker_sys_interval", [ + {default, 60}, + {datatype, integer} +]}. + +%%-------------------------------------------------------------------- +%% MQTT PubSub +%%-------------------------------------------------------------------- + +{mapping, "mqtt.pubsub.pool_size", "emqttd.pubsub", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "mqtt.pubsub.by_clientid", "emqttd.pubsub", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "mqtt.pubsub.async", "emqttd.pubsub", [ + {default, true}, + {datatype, {enum, [true, false]}}, + hidden +]}. + +{translation, "emqttd.pubsub", fun(Conf) -> + [{pool_size, cuttlefish:conf_get("mqtt.pubsub.pool_size", Conf)}, + {by_clientid, cuttlefish:conf_get("mqtt.pubsub.by_clientid", Conf)}, + {async, cuttlefish:conf_get("mqtt.pubsub.async", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Listeners +%%-------------------------------------------------------------------- + +{mapping, "mqtt.listener.tcp", "emqttd.listeners", [ + {default, 1883}, + {datatype, [integer, ip]} +]}. + +{mapping, "mqtt.listener.tcp.acceptors", "emqttd.listeners", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "mqtt.listener.tcp.max_clients", "emqttd.listeners", [ + {default, 1024}, + {datatype, integer} +]}. + +{mapping, "mqtt.listener.ssl", "emqttd.listeners", [ + {default, 8883}, + {datatype, [integer, ip]} +]}. + +{mapping, "mqtt.listener.ssl.acceptors", "emqttd.listeners", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "mqtt.listener.ssl.max_clients", "emqttd.listeners", [ + {default, 512}, + {datatype, integer} +]}. + +{mapping, "mqtt.listener.http", "emqttd.listeners", [ + {default, 8883}, + {datatype, [integer, ip]} +]}. + +{mapping, "mqtt.listener.http.acceptors", "emqttd.listeners", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "mqtt.listener.http.max_clients", "emqttd.listeners", [ + {default, 64}, + {datatype, integer} +]}. + +{translation, "emqttd.listeners", fun(Conf) -> + TcpListeners = case cuttlefish:conf_get("mqtt.listener.tcp", Conf) of + undefined -> + []; + TcpPort -> + TcpOpts = [{acceptors, cuttlefish:conf_get("mqtt.listener.tcp.acceptors", Conf)}, + {max_clients, cuttlefish:conf_get("mqtt.listener.tcp.max_clients", Conf)}], + [{tcp, TcpPort, TcpOpts}] + end, + SslListeners = case cuttlefish:conf_get("mqtt.listener.ssl", Conf) of + undefined -> + []; + SslPort -> + SslOpts = [{acceptors, cuttlefish:conf_get("mqtt.listener.ssl.acceptors", Conf)}, + {max_clients, cuttlefish:conf_get("mqtt.listener.ssl.max_clients", Conf)}], + [{ssl, SslPort, SslOpts}] + end, + HttpListeners = case cuttlefish:conf_get("mqtt.listener.http", Conf) of + undefined -> + []; + HttPort -> + HttpOpts = [{acceptors, cuttlefish:conf_get("mqtt.listener.http.acceptors", Conf)}, + {max_clients, cuttlefish:conf_get("mqtt.listener.http.max_clients", Conf)}], + [{http, HttPort, HttpOpts}] + end, + TcpListeners ++ SslListeners ++ HttpListeners +end}. + +%%-------------------------------------------------------------------- +%% MQTT Bridge +%%-------------------------------------------------------------------- + +{mapping, "mqtt.bridge.max_queue_len", "emqttd.bridge", [ + {default, 10000}, + {datatype, integer} +]}. + +{mapping, "mqtt.bridge.ping_down_interval", "emqttd.bridge", [ + {default, 1}, + {datatype, integer} +]}. + +{translation, "emqttd.bridge", fun(Conf) -> + [{max_queue_len, cuttlefish:conf_get("mqtt.bridge.max_queue_len", Conf)}, + {ping_down_interval, cuttlefish:conf_get("mqtt.bridge.ping_down_interval", Conf)}] +end}. + +%%------------------------------------------------------------------- +%% MQTT Plugins +%%------------------------------------------------------------------- + +{mapping, "mqtt.plugins.etc_dir", "emqttd.plugins_etc_dir", [ + {datatype, string} +]}. + +{mapping, "mqtt.plugins.loaded_file", "emqttd.plugins_loaded_file", [ + {datatype, string} +]}. + +%%-------------------------------------------------------------------- +%% System Monitor +%%-------------------------------------------------------------------- + +%% @doc Long GC, don't monitor in production mode for: +%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 +{mapping, "sysmon.long_gc", "emqttd.sysmon", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +%% @doc Long Schedule(ms) +{mapping, "sysmon.long_schedule", "emqttd.sysmon", [ + {default, 1000}, + {datatype, integer} +]}. + +%% @doc Large Heap +{mapping, "sysmon.large_heap", "emqttd.sysmon", [ + {default, "8MB"}, + {datatype, bytesize} +]}. + +%% @doc Monitor Busy Port +{mapping, "sysmon.busy_port", "emqttd.sysmon", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +%% @doc Monitor Busy Dist Port +{mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{translation, "emqttd.sysmon", fun(Conf) -> + [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)}, + {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)}, + {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)}, + {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)}, + {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}] +end}. + +{mapping, "platform_etc_dir", "emqttd.platform_etc_dir", [ + {datatype, directory}, + {default, "./etc"} +]}. + +{mapping, "platform_log_dir", "emqttd.platform_log_dir", [ + {datatype, directory}, + {default, "./log"} +]}. + +{mapping, "platform_data_dir", "emqttd.platform_data_dir", [ + {datatype, directory}, + {default, "./data"} +]}. +