emq.schema 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. %%-*- mode: erlang -*-
  2. %% EMQ config mapping
  3. %%--------------------------------------------------------------------
  4. %% Erlang Node
  5. %%--------------------------------------------------------------------
  6. %% @doc Erlang node name
  7. {mapping, "node.name", "vm_args.-name", [
  8. {default, "emqttd@127.0.0.1"}
  9. ]}.
  10. %% @doc Secret cookie for distributed erlang node
  11. {mapping, "node.cookie", "vm_args.-setcookie", [
  12. {default, "emqsecretcookie"}
  13. ]}.
  14. %% @doc SMP Support
  15. {mapping, "node.smp", "vm_args.-smp", [
  16. {default, auto},
  17. {datatype, {enum, [enable, auto, disable]}},
  18. hidden
  19. ]}.
  20. %% @doc http://erlang.org/doc/man/heart.html
  21. {mapping, "node.heartbeat", "vm_args.-heart", [
  22. {datatype, flag},
  23. hidden
  24. ]}.
  25. {translation, "vm_args.-heart", fun(Conf) ->
  26. case cuttlefish:conf_get("node.heartbeat", Conf) of
  27. true -> "";
  28. false -> cuttlefish:invalid("should be 'on' or comment the line!")
  29. end
  30. end}.
  31. %% @doc Enable Kernel Poll
  32. {mapping, "node.kernel_poll", "vm_args.+K", [
  33. {default, on},
  34. {datatype, flag},
  35. hidden
  36. ]}.
  37. %% @doc More information at: http://erlang.org/doc/man/erl.html
  38. {mapping, "node.async_threads", "vm_args.+A", [
  39. {default, 64},
  40. {datatype, integer},
  41. {validators, ["range:0-1024"]}
  42. ]}.
  43. %% @doc Erlang Process Limit
  44. {mapping, "node.process_limit", "vm_args.+P", [
  45. {datatype, integer},
  46. {default, 256000},
  47. hidden
  48. ]}.
  49. %% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q
  50. %% @doc The number of concurrent ports/sockets
  51. %% Valid range is 1024-134217727
  52. {mapping, "node.max_ports",
  53. cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [
  54. {default, 262144},
  55. {datatype, integer},
  56. {validators, ["range4ports"]}
  57. ]}.
  58. {validator, "range4ports", "must be 1024 to 134217727",
  59. fun(X) -> X >= 1024 andalso X =< 134217727 end}.
  60. %% @doc http://www.erlang.org/doc/man/erl.html#%2bzdbbl
  61. {mapping, "node.dist_buffer_size", "vm_args.+zdbbl", [
  62. {datatype, bytesize},
  63. {commented, "32MB"},
  64. hidden,
  65. {validators, ["zdbbl_range"]}
  66. ]}.
  67. {translation, "vm_args.+zdbbl",
  68. fun(Conf) ->
  69. ZDBBL = cuttlefish:conf_get("node.dist_buffer_size", Conf, undefined),
  70. case ZDBBL of
  71. undefined -> undefined;
  72. X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes;
  73. _ -> undefined
  74. end
  75. end
  76. }.
  77. {validator, "zdbbl_range", "must be between 1KB and 2097151KB",
  78. fun(ZDBBL) ->
  79. %% 2097151KB = 2147482624
  80. ZDBBL >= 1024 andalso ZDBBL =< 2147482624
  81. end
  82. }.
  83. %% @doc http://www.erlang.org/doc/man/erlang.html#system_flag-2
  84. {mapping, "node.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [
  85. {default, 1000},
  86. {datatype, integer},
  87. hidden,
  88. {validators, ["positive_integer"]}
  89. ]}.
  90. {validator, "positive_integer", "must be a positive integer",
  91. fun(X) -> X >= 0 end}.
  92. %% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES,
  93. %% R16+ uses +e
  94. %% @doc The ETS table limit
  95. {mapping, "node.max_ets_tables",
  96. cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [
  97. {default, 256000},
  98. {datatype, integer},
  99. hidden
  100. ]}.
  101. %% @doc Set the location of crash dumps
  102. {mapping, "node.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [
  103. {default, "{{crash_dump}}"},
  104. {datatype, file},
  105. hidden
  106. ]}.
  107. %% @doc http://www.erlang.org/doc/man/kernel_app.html#net_ticktime
  108. {mapping, "node.dist_net_ticktime", "vm_args.-kernel net_ticktime", [
  109. {commented, 60},
  110. {datatype, integer},
  111. hidden
  112. ]}.
  113. %% @doc http://www.erlang.org/doc/man/kernel_app.html
  114. {mapping, "node.dist_listen_min", "kernel.inet_dist_listen_min", [
  115. {commented, 6369},
  116. {datatype, integer},
  117. hidden
  118. ]}.
  119. %% @see node.dist_listen_min
  120. {mapping, "node.dist_listen_max", "kernel.inet_dist_listen_max", [
  121. {commented, 6369},
  122. {datatype, integer},
  123. hidden
  124. ]}.
  125. %%--------------------------------------------------------------------
  126. %% Log
  127. %%--------------------------------------------------------------------
  128. {mapping, "log.dir", "lager.log_dir", [
  129. {default, "log"},
  130. {datatype, string}
  131. ]}.
  132. {mapping, "log.console", "lager.handlers", [
  133. {default, file},
  134. {datatype, {enum, [off, file, console, both]}}
  135. ]}.
  136. {mapping, "log.console.level", "lager.handlers", [
  137. {default, info},
  138. {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}}
  139. ]}.
  140. {mapping, "log.console.file", "lager.handlers", [
  141. {default, "log/console.log"},
  142. {datatype, file}
  143. ]}.
  144. {mapping, "log.error.file", "lager.handlers", [
  145. {default, "log/error.log"},
  146. {datatype, file}
  147. ]}.
  148. {mapping, "log.syslog", "lager.handlers", [
  149. {default, off},
  150. {datatype, flag}
  151. ]}.
  152. {mapping, "log.syslog.identity", "lager.handlers", [
  153. {default, "emq"},
  154. {datatype, string}
  155. ]}.
  156. {mapping, "log.syslog.facility", "lager.handlers", [
  157. {default, local0},
  158. {datatype, {enum, [daemon, local0, local1, local2, local3, local4, local5, local6, local7]}}
  159. ]}.
  160. {mapping, "log.syslog.level", "lager.handlers", [
  161. {default, err},
  162. {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency]}}
  163. ]}.
  164. {mapping, "log.error.redirect", "lager.error_logger_redirect", [
  165. {default, on},
  166. {datatype, flag},
  167. hidden
  168. ]}.
  169. {mapping, "log.error.messages_per_second", "lager.error_logger_hwm", [
  170. {default, 1000},
  171. {datatype, integer},
  172. hidden
  173. ]}.
  174. {translation,
  175. "lager.handlers",
  176. fun(Conf) ->
  177. ErrorHandler = case cuttlefish:conf_get("log.error.file", Conf) of
  178. undefined -> [];
  179. ErrorFilename -> [{lager_file_backend, [{file, ErrorFilename},
  180. {level, error},
  181. {size, 10485760},
  182. {date, "$D0"},
  183. {count, 5}]}]
  184. end,
  185. ConsoleLogLevel = cuttlefish:conf_get("log.console.level", Conf),
  186. ConsoleLogFile = cuttlefish:conf_get("log.console.file", Conf),
  187. ConsoleHandler = {lager_console_backend, ConsoleLogLevel},
  188. ConsoleFileHandler = {lager_file_backend, [{file, ConsoleLogFile},
  189. {level, ConsoleLogLevel},
  190. {size, 10485760},
  191. {date, "$D0"},
  192. {count, 5}]},
  193. ConsoleHandlers = case cuttlefish:conf_get("log.console", Conf) of
  194. off -> [];
  195. file -> [ConsoleFileHandler];
  196. console -> [ConsoleHandler];
  197. both -> [ConsoleHandler, ConsoleFileHandler];
  198. _ -> []
  199. end,
  200. SyslogHandler = case cuttlefish:conf_get("log.syslog", Conf) of
  201. false -> [];
  202. true -> [{lager_syslog_backend,
  203. [cuttlefish:conf_get("log.syslog.identity", Conf),
  204. cuttlefish:conf_get("log.syslog.facility", Conf),
  205. cuttlefish:conf_get("log.syslog.level", Conf)]}]
  206. end,
  207. ConsoleHandlers ++ ErrorHandler ++ SyslogHandler
  208. end
  209. }.
  210. {mapping, "log.crash", "lager.crash_log", [
  211. {default, on},
  212. {datatype, flag}
  213. ]}.
  214. {mapping, "log.crash.file", "lager.crash_log", [
  215. {default, "log/crash.log"},
  216. {datatype, file}
  217. ]}.
  218. {translation,
  219. "lager.crash_log",
  220. fun(Conf) ->
  221. case cuttlefish:conf_get("log.crash", Conf) of
  222. false -> undefined;
  223. _ ->
  224. cuttlefish:conf_get("log.crash.file", Conf, "./log/crash.log")
  225. end
  226. end}.
  227. {mapping, "sasl", "sasl.sasl_error_logger", [
  228. {default, off},
  229. {datatype, flag},
  230. hidden
  231. ]}.
  232. %%--------------------------------------------------------------------
  233. %% Allow Anonymous and Default ACL
  234. %%--------------------------------------------------------------------
  235. %% @doc Allow Anonymous
  236. {mapping, "mqtt.allow_anonymous", "emqttd.allow_anonymous", [
  237. {default, false},
  238. {datatype, {enum, [true, false]}}
  239. ]}.
  240. %% @doc Default ACL File
  241. {mapping, "mqtt.acl_file", "emqttd.acl_file", [
  242. {datatype, string},
  243. hidden
  244. ]}.
  245. %% @doc Cache ACL for PUBLISH
  246. {mapping, "mqtt.cache_acl", "emqttd.cache_acl", [
  247. {default, true},
  248. {datatype, {enum, [true, false]}}
  249. ]}.
  250. %%--------------------------------------------------------------------
  251. %% MQTT Protocol
  252. %%--------------------------------------------------------------------
  253. %% @doc Set the Max ClientId Length Allowed.
  254. {mapping, "mqtt.max_clientid_len", "emqttd.protocol", [
  255. {default, 1024},
  256. {datatype, integer}
  257. ]}.
  258. %% @doc Max Packet Size Allowed, 64K by default.
  259. {mapping, "mqtt.max_packet_size", "emqttd.protocol", [
  260. {default, "64KB"},
  261. {datatype, bytesize}
  262. ]}.
  263. {translation, "emqttd.protocol", fun(Conf) ->
  264. [{max_clientid_len, cuttlefish:conf_get("mqtt.max_clientid_len", Conf)},
  265. {max_packet_size, cuttlefish:conf_get("mqtt.max_packet_size", Conf)}]
  266. end}.
  267. %%--------------------------------------------------------------------
  268. %% MQTT Connection
  269. %%--------------------------------------------------------------------
  270. %% @doc Force the client to GC: integer
  271. {mapping, "mqtt.conn.force_gc_count", "emqttd.conn_force_gc_count", [
  272. {datatype, integer}
  273. ]}.
  274. %%--------------------------------------------------------------------
  275. %% MQTT Client
  276. %%--------------------------------------------------------------------
  277. %% @doc Client Idle Timeout.
  278. {mapping, "mqtt.client.idle_timeout", "emqttd.client", [
  279. {default, "30s"},
  280. {datatype, {duration, ms}}
  281. ]}.
  282. %% @doc Enable Stats of Client.
  283. {mapping, "mqtt.client.enable_stats", "emqttd.client", [
  284. {default, off},
  285. {datatype, flag}
  286. ]}.
  287. %% @doc Client
  288. {translation, "emqttd.client", fun(Conf) ->
  289. [{client_idle_timeout, cuttlefish:conf_get("mqtt.client.idle_timeout", Conf)},
  290. {client_enable_stats, cuttlefish:conf_get("mqtt.client.enable_stats", Conf)}]
  291. end}.
  292. %%--------------------------------------------------------------------
  293. %% MQTT Session
  294. %%--------------------------------------------------------------------
  295. %% @doc Upgrade QoS?
  296. {mapping, "mqtt.session.upgrade_qos", "emqttd.session", [
  297. {default, off},
  298. {datatype, flag}
  299. ]}.
  300. %% @doc Max number of QoS 1 and 2 messages that can be “inflight” at one time.
  301. %% 0 means no limit
  302. {mapping, "mqtt.session.max_inflight", "emqttd.session", [
  303. {default, 100},
  304. {datatype, integer}
  305. ]}.
  306. %% @doc Retry interval for redelivering QoS1/2 messages.
  307. {mapping, "mqtt.session.retry_interval", "emqttd.session", [
  308. {default, "20s"},
  309. {datatype, {duration, ms}}
  310. ]}.
  311. %% @doc Max Packets that Awaiting PUBREL, 0 means no limit
  312. {mapping, "mqtt.session.max_awaiting_rel", "emqttd.session", [
  313. {default, 0},
  314. {datatype, integer}
  315. ]}.
  316. %% @doc Awaiting PUBREL Timeout
  317. {mapping, "mqtt.session.await_rel_timeout", "emqttd.session", [
  318. {default, "20s"},
  319. {datatype, {duration, ms}}
  320. ]}.
  321. %% @doc Enable Stats
  322. {mapping, "mqtt.session.enable_stats", "emqttd.session", [
  323. {default, off},
  324. {datatype, flag}
  325. ]}.
  326. %% @doc Session Expiry Interval
  327. {mapping, "mqtt.session.expiry_interval", "emqttd.session", [
  328. {default, "2h"},
  329. {datatype, {duration, ms}}
  330. ]}.
  331. {translation, "emqttd.session", fun(Conf) ->
  332. [{upgrade_qos, cuttlefish:conf_get("mqtt.session.upgrade_qos", Conf)},
  333. {max_inflight, cuttlefish:conf_get("mqtt.session.max_inflight", Conf)},
  334. {retry_interval, cuttlefish:conf_get("mqtt.session.retry_interval", Conf)},
  335. {max_awaiting_rel, cuttlefish:conf_get("mqtt.session.max_awaiting_rel", Conf)},
  336. {await_rel_timeout, cuttlefish:conf_get("mqtt.session.await_rel_timeout", Conf)},
  337. {enable_stats, cuttlefish:conf_get("mqtt.session.enable_stats", Conf)},
  338. {expiry_interval, cuttlefish:conf_get("mqtt.session.expiry_interval", Conf)}]
  339. end}.
  340. %%--------------------------------------------------------------------
  341. %% MQTT Queue
  342. %%--------------------------------------------------------------------
  343. %% @doc Type: simple | priority
  344. {mapping, "mqtt.queue.type", "emqttd.queue", [
  345. {default, simple},
  346. {datatype, atom}
  347. ]}.
  348. %% @doc Topic Priority: 0~255, Default is 0
  349. {mapping, "mqtt.queue.priority", "emqttd.queue", [
  350. {default, ""},
  351. {datatype, string}
  352. ]}.
  353. %% @doc Max queue length. Enqueued messages when persistent client disconnected, or inflight window is full.
  354. {mapping, "mqtt.queue.max_length", "emqttd.queue", [
  355. {default, infinity},
  356. {datatype, [integer, {atom, infinity}]}
  357. ]}.
  358. %% @doc Low-water mark of queued messages
  359. {mapping, "mqtt.queue.low_watermark", "emqttd.queue", [
  360. {default, "20%"},
  361. {datatype, string}
  362. ]}.
  363. %% @doc High-water mark of queued messages
  364. {mapping, "mqtt.queue.high_watermark", "emqttd.queue", [
  365. {default, "60%"},
  366. {datatype, string}
  367. ]}.
  368. %% @doc Queue Qos0 messages?
  369. {mapping, "mqtt.queue.qos0", "emqttd.queue", [
  370. {default, true},
  371. {datatype, {enum, [true, false]}}
  372. ]}.
  373. {translation, "emqttd.queue", fun(Conf) ->
  374. Parse = fun(S) ->
  375. {match, [N]} = re:run(S, "^([0-9]+)%$", [{capture, all_but_first, list}]),
  376. list_to_integer(N) / 100
  377. end,
  378. Opts = [{type, cuttlefish:conf_get("mqtt.queue.type", Conf, simple)},
  379. {max_length, cuttlefish:conf_get("mqtt.queue.max_length", Conf)},
  380. {low_watermark, Parse(cuttlefish:conf_get("mqtt.queue.low_watermark", Conf))},
  381. {high_watermark, Parse(cuttlefish:conf_get("mqtt.queue.high_watermark", Conf))},
  382. {queue_qos0, cuttlefish:conf_get("mqtt.queue.qos0", Conf)}],
  383. case cuttlefish:conf_get("mqtt.queue.priority", Conf) of
  384. undefined -> Opts;
  385. V -> [{priority,
  386. [begin [T, P] = string:tokens(S, "="),
  387. {T, list_to_integer(P)}
  388. end || S <- string:tokens(V, ",")]}|Opts]
  389. end
  390. end}.
  391. %%--------------------------------------------------------------------
  392. %% MQTT Broker
  393. %%--------------------------------------------------------------------
  394. {mapping, "mqtt.broker.sys_interval", "emqttd.broker_sys_interval", [
  395. {default, 60},
  396. {datatype, integer}
  397. ]}.
  398. %%--------------------------------------------------------------------
  399. %% MQTT PubSub
  400. %%--------------------------------------------------------------------
  401. {mapping, "mqtt.pubsub.pool_size", "emqttd.pubsub", [
  402. {default, 8},
  403. {datatype, integer}
  404. ]}.
  405. {mapping, "mqtt.pubsub.by_clientid", "emqttd.pubsub", [
  406. {default, true},
  407. {datatype, {enum, [true, false]}}
  408. ]}.
  409. {mapping, "mqtt.pubsub.async", "emqttd.pubsub", [
  410. {default, true},
  411. {datatype, {enum, [true, false]}}
  412. ]}.
  413. {translation, "emqttd.pubsub", fun(Conf) ->
  414. [{pool_size, cuttlefish:conf_get("mqtt.pubsub.pool_size", Conf)},
  415. {by_clientid, cuttlefish:conf_get("mqtt.pubsub.by_clientid", Conf)},
  416. {async, cuttlefish:conf_get("mqtt.pubsub.async", Conf)}]
  417. end}.
  418. %%--------------------------------------------------------------------
  419. %% MQTT Bridge
  420. %%--------------------------------------------------------------------
  421. {mapping, "mqtt.bridge.max_queue_len", "emqttd.bridge", [
  422. {default, 10000},
  423. {datatype, integer}
  424. ]}.
  425. {mapping, "mqtt.bridge.ping_down_interval", "emqttd.bridge", [
  426. {default, 1},
  427. {datatype, integer}
  428. ]}.
  429. {translation, "emqttd.bridge", fun(Conf) ->
  430. [{max_queue_len, cuttlefish:conf_get("mqtt.bridge.max_queue_len", Conf)},
  431. {ping_down_interval, cuttlefish:conf_get("mqtt.bridge.ping_down_interval", Conf)}]
  432. end}.
  433. %%-------------------------------------------------------------------
  434. %% MQTT Plugins
  435. %%-------------------------------------------------------------------
  436. {mapping, "mqtt.plugins.etc_dir", "emqttd.plugins_etc_dir", [
  437. {datatype, string}
  438. ]}.
  439. {mapping, "mqtt.plugins.loaded_file", "emqttd.plugins_loaded_file", [
  440. {datatype, string}
  441. ]}.
  442. %%--------------------------------------------------------------------
  443. %% MQTT Listeners
  444. %%--------------------------------------------------------------------
  445. {mapping, "mqtt.listener.tcp", "emqttd.listeners", [
  446. %% {default, 1883},
  447. {datatype, [integer, ip]}
  448. ]}.
  449. {mapping, "mqtt.listener.tcp.acceptors", "emqttd.listeners", [
  450. {default, 8},
  451. {datatype, integer}
  452. ]}.
  453. {mapping, "mqtt.listener.tcp.max_clients", "emqttd.listeners", [
  454. {default, 1024},
  455. {datatype, integer}
  456. ]}.
  457. {mapping, "mqtt.listener.tcp.rate_limit", "emqttd.listeners", [
  458. {default, undefined},
  459. {datatype, string}
  460. ]}.
  461. {mapping, "mqtt.listener.tcp.backlog", "emqttd.listeners", [
  462. {default, 1024},
  463. {datatype, integer}
  464. ]}.
  465. {mapping, "mqtt.listener.tcp.recbuf", "emqttd.listeners", [
  466. {datatype, integer},
  467. hidden
  468. ]}.
  469. {mapping, "mqtt.listener.tcp.sndbuf", "emqttd.listeners", [
  470. {datatype, integer},
  471. hidden
  472. ]}.
  473. {mapping, "mqtt.listener.tcp.buffer", "emqttd.listeners", [
  474. {datatype, integer},
  475. hidden
  476. ]}.
  477. {mapping, "mqtt.listener.tcp.tune_buffer", "emqttd.listeners", [
  478. {default, off},
  479. {datatype, flag}
  480. ]}.
  481. {mapping, "mqtt.listener.tcp.nodelay", "emqttd.listeners", [
  482. {datatype, {enum, [true, false]}},
  483. hidden
  484. ]}.
  485. {mapping, "mqtt.listener.ssl", "emqttd.listeners", [
  486. %% {default, 8883},
  487. {datatype, [integer, ip]}
  488. ]}.
  489. {mapping, "mqtt.listener.ssl.acceptors", "emqttd.listeners", [
  490. {default, 8},
  491. {datatype, integer}
  492. ]}.
  493. {mapping, "mqtt.listener.ssl.max_clients", "emqttd.listeners", [
  494. {default, 512},
  495. {datatype, integer}
  496. ]}.
  497. {mapping, "mqtt.listener.ssl.rate_limit", "emqttd.listeners", [
  498. {datatype, string}
  499. ]}.
  500. {mapping, "mqtt.listener.ssl.tls_versions", "emqttd.listeners", [
  501. {datatype, string}
  502. ]}.
  503. {mapping, "mqtt.listener.ssl.handshake_timeout", "emqttd.listeners", [
  504. {default, "15s"},
  505. {datatype, {duration, ms}}
  506. ]}.
  507. {mapping, "mqtt.listener.ssl.keyfile", "emqttd.listeners", [
  508. {datatype, string}
  509. ]}.
  510. {mapping, "mqtt.listener.ssl.certfile", "emqttd.listeners", [
  511. {datatype, string}
  512. ]}.
  513. {mapping, "mqtt.listener.ssl.cacertfile", "emqttd.listeners", [
  514. {datatype, string}
  515. ]}.
  516. {mapping, "mqtt.listener.ssl.verify", "emqttd.listeners", [
  517. {datatype, atom}
  518. ]}.
  519. {mapping, "mqtt.listener.ssl.fail_if_no_peer_cert", "emqttd.listeners", [
  520. {datatype, {enum, [true, false]}}
  521. ]}.
  522. {mapping, "mqtt.listener.http", "emqttd.listeners", [
  523. %% {default, 8083},
  524. {datatype, [integer, ip]}
  525. ]}.
  526. {mapping, "mqtt.listener.http.acceptors", "emqttd.listeners", [
  527. {default, 8},
  528. {datatype, integer}
  529. ]}.
  530. {mapping, "mqtt.listener.http.max_clients", "emqttd.listeners", [
  531. {default, 64},
  532. {datatype, integer}
  533. ]}.
  534. {mapping, "mqtt.listener.https", "emqttd.listeners", [
  535. %%{default, 8084},
  536. {datatype, [integer, ip]}
  537. ]}.
  538. {mapping, "mqtt.listener.https.acceptors", "emqttd.listeners", [
  539. {default, 8},
  540. {datatype, integer}
  541. ]}.
  542. {mapping, "mqtt.listener.https.max_clients", "emqttd.listeners", [
  543. {default, 64},
  544. {datatype, integer}
  545. ]}.
  546. {mapping, "mqtt.listener.https.handshake_timeout", "emqttd.listeners", [
  547. {default, 15},
  548. {datatype, integer}
  549. ]}.
  550. {mapping, "mqtt.listener.https.keyfile", "emqttd.listeners", [
  551. {datatype, string}
  552. ]}.
  553. {mapping, "mqtt.listener.https.certfile", "emqttd.listeners", [
  554. {datatype, string}
  555. ]}.
  556. {mapping, "mqtt.listener.https.cacertfile", "emqttd.listeners", [
  557. {datatype, string}
  558. ]}.
  559. {mapping, "mqtt.listener.https.verify", "emqttd.listeners", [
  560. {datatype, atom}
  561. ]}.
  562. {mapping, "mqtt.listener.https.fail_if_no_peer_cert", "emqttd.listeners", [
  563. {datatype, {enum, [true, false]}}
  564. ]}.
  565. {translation, "emqttd.listeners", fun(Conf) ->
  566. Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
  567. LisOpts = fun(Prefix) ->
  568. Filter([{acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)},
  569. {max_clients, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)},
  570. {tune_buffer, cuttlefish:conf_get(Prefix ++ ".tune_buffer", Conf, undefined)}])
  571. end,
  572. TcpOpts = fun(Prefix) ->
  573. Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},
  574. {recbuf, cuttlefish:conf_get(Prefix ++ ".recbuf", Conf, undefined)},
  575. {sndbuf, cuttlefish:conf_get(Prefix ++ ".sndbuf", Conf, undefined)},
  576. {buffer, cuttlefish:conf_get(Prefix ++ ".buffer", Conf, undefined)},
  577. {nodelay, cuttlefish:conf_get(Prefix ++ ".nodelay", Conf, true)}])
  578. end,
  579. SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
  580. SslOpts = fun(Prefix) ->
  581. Versions = case SplitFun(cuttlefish:conf_get(Prefix ++ ".tls_versions", Conf, undefined)) of
  582. undefined -> undefined;
  583. L -> [list_to_atom(V) || V <- L]
  584. end,
  585. Filter([{versions, Versions},
  586. {handshake_timeout, cuttlefish:conf_get(Prefix ++ ".handshake_timeout", Conf), undefined},
  587. {keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
  588. {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
  589. {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
  590. {verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
  591. {fail_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".fail_if_no_peer_cert", Conf, undefined)}])
  592. end,
  593. Listeners = fun(Name) when is_atom(Name) ->
  594. Key = "mqtt.listener." ++ atom_to_list(Name),
  595. case cuttlefish:conf_get(Key, Conf, undefined) of
  596. undefined ->
  597. [];
  598. Port ->
  599. ConnOpts = Filter([{rate_limit, cuttlefish:conf_get(Key ++ ".rate_limit", Conf, undefined)}]),
  600. Opts = [{connopts, ConnOpts}, {sockopts, TcpOpts(Key)} | LisOpts(Key)],
  601. [{Name, Port, case Name =:= ssl orelse Name =:= https of
  602. true -> [{sslopts, SslOpts(Key)} | Opts];
  603. false -> Opts
  604. end}]
  605. end
  606. end,
  607. lists:append([Listeners(tcp), Listeners(ssl), Listeners(http), Listeners(https)])
  608. end}.
  609. %%--------------------------------------------------------------------
  610. %% System Monitor
  611. %%--------------------------------------------------------------------
  612. %% @doc Long GC, don't monitor in production mode for:
  613. %% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
  614. {mapping, "sysmon.long_gc", "emqttd.sysmon", [
  615. {default, false},
  616. {datatype, {enum, [true, false]}}
  617. ]}.
  618. %% @doc Long Schedule(ms)
  619. {mapping, "sysmon.long_schedule", "emqttd.sysmon", [
  620. {default, 1000},
  621. {datatype, integer}
  622. ]}.
  623. %% @doc Large Heap
  624. {mapping, "sysmon.large_heap", "emqttd.sysmon", [
  625. {default, "8MB"},
  626. {datatype, bytesize}
  627. ]}.
  628. %% @doc Monitor Busy Port
  629. {mapping, "sysmon.busy_port", "emqttd.sysmon", [
  630. {default, false},
  631. {datatype, {enum, [true, false]}}
  632. ]}.
  633. %% @doc Monitor Busy Dist Port
  634. {mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [
  635. {default, true},
  636. {datatype, {enum, [true, false]}}
  637. ]}.
  638. {translation, "emqttd.sysmon", fun(Conf) ->
  639. [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)},
  640. {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)},
  641. {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)},
  642. {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)},
  643. {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}]
  644. end}.