emq.schema 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. %%-*- mode: erlang -*-
  2. %% EMQ R2.3 config mapping
  3. %%--------------------------------------------------------------------
  4. %% Cluster
  5. %%--------------------------------------------------------------------
  6. %% @doc Cluster name
  7. {mapping, "cluster.name", "ekka.cluster_name", [
  8. {default, emqcl},
  9. {datatype, atom}
  10. ]}.
  11. %% @doc Cluster discovery
  12. {mapping, "cluster.discovery", "ekka.cluster_discovery", [
  13. {default, manual},
  14. {datatype, atom}
  15. ]}.
  16. %% @doc Clean down node from the cluster
  17. {mapping, "cluster.autoclean", "ekka.cluster_autoclean", [
  18. {datatype, {duration, ms}}
  19. ]}.
  20. %% @doc Cluster autoheal
  21. {mapping, "cluster.autoheal", "ekka.cluster_autoheal", [
  22. {datatype, flag},
  23. {default, off}
  24. ]}.
  25. %%--------------------------------------------------------------------
  26. %% Cluster by static node list
  27. {mapping, "cluster.static.seeds", "ekka.cluster_discovery", [
  28. {datatype, string}
  29. ]}.
  30. %%--------------------------------------------------------------------
  31. %% Cluster by UDP Multicast
  32. {mapping, "cluster.mcast.addr", "ekka.cluster_discovery", [
  33. {default, "239.192.0.1"},
  34. {datatype, string}
  35. ]}.
  36. {mapping, "cluster.mcast.ports", "ekka.cluster_discovery", [
  37. {default, "4369"},
  38. {datatype, string}
  39. ]}.
  40. {mapping, "cluster.mcast.iface", "ekka.cluster_discovery", [
  41. {datatype, string},
  42. {default, "0.0.0.0"}
  43. ]}.
  44. {mapping, "cluster.mcast.ttl", "ekka.cluster_discovery", [
  45. {datatype, integer},
  46. {default, 255}
  47. ]}.
  48. {mapping, "cluster.mcast.loop", "ekka.cluster_discovery", [
  49. {datatype, flag},
  50. {default, on}
  51. ]}.
  52. {mapping, "cluster.mcast.sndbuf", "ekka.cluster_discovery", [
  53. {datatype, bytesize},
  54. {default, "16KB"}
  55. ]}.
  56. {mapping, "cluster.mcast.recbuf", "ekka.cluster_discovery", [
  57. {datatype, bytesize},
  58. {default, "16KB"}
  59. ]}.
  60. {mapping, "cluster.mcast.buffer", "ekka.cluster_discovery", [
  61. {datatype, bytesize},
  62. {default, "32KB"}
  63. ]}.
  64. %%--------------------------------------------------------------------
  65. %% Cluster by DNS A Record
  66. {mapping, "cluster.dns.name", "ekka.cluster_discovery", [
  67. {datatype, string}
  68. ]}.
  69. {mapping, "cluster.dns.app", "ekka.cluster_discovery", [
  70. {datatype, string}
  71. ]}.
  72. %%--------------------------------------------------------------------
  73. %% Cluster using etcd
  74. {mapping, "cluster.etcd.server", "ekka.cluster_discovery", [
  75. {datatype, string}
  76. ]}.
  77. {mapping, "cluster.etcd.prefix", "ekka.cluster_discovery", [
  78. {datatype, string}
  79. ]}.
  80. {mapping, "cluster.etcd.node_ttl", "ekka.cluster_discovery", [
  81. {datatype, {duration, ms}},
  82. {default, "1m"}
  83. ]}.
  84. %%--------------------------------------------------------------------
  85. %% Cluster on K8s
  86. {mapping, "cluster.k8s.apiserver", "ekka.cluster_discovery", [
  87. {datatype, string}
  88. ]}.
  89. {mapping, "cluster.k8s.service_name", "ekka.cluster_discovery", [
  90. {datatype, string}
  91. ]}.
  92. {mapping, "cluster.k8s.address_type", "ekka.cluster_discovery", [
  93. {datatype, {enum, [ip, dns]}}
  94. ]}.
  95. {mapping, "cluster.k8s.app_name", "ekka.cluster_discovery", [
  96. {datatype, string}
  97. ]}.
  98. {translation, "ekka.cluster_discovery", fun(Conf) ->
  99. Strategy = cuttlefish:conf_get("cluster.discovery", Conf),
  100. Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
  101. IpPort = fun(S) ->
  102. [Addr, Port] = string:tokens(S, ":"),
  103. {ok, Ip} = inet:parse_address(Addr),
  104. {Ip, Port}
  105. end,
  106. Options = fun(static) ->
  107. [{seeds, [list_to_atom(S) || S <- string:tokens(cuttlefish:conf_get("cluster.static.seeds", Conf, ""), ",")]}];
  108. (mcast) ->
  109. {ok, Addr} = inet:parse_address(cuttlefish:conf_get("cluster.mcast.addr", Conf)),
  110. {ok, Iface} = inet:parse_address(cuttlefish:conf_get("cluster.mcast.iface", Conf)),
  111. Ports = [list_to_integer(S) || S <- string:tokens(cuttlefish:conf_get("cluster.mcast.ports", Conf), ",")],
  112. [{addr, Addr}, {ports, Ports}, {iface, Iface},
  113. {ttl, cuttlefish:conf_get("cluster.mcast.ttl", Conf, 1)},
  114. {loop, cuttlefish:conf_get("cluster.mcast.loop", Conf, true)}];
  115. (dns) ->
  116. [{name, cuttlefish:conf_get("cluster.dns.name", Conf)},
  117. {app, cuttlefish:conf_get("cluster.dns.app", Conf)}];
  118. (etcd) ->
  119. [{server, string:tokens(cuttlefish:conf_get("cluster.etcd.server", Conf), ",")},
  120. {prefix, cuttlefish:conf_get("cluster.etcd.prefix", Conf, "emqcl")},
  121. {node_ttl, cuttlefish:conf_get("cluster.etcd.node_ttl", Conf, 60)}];
  122. (k8s) ->
  123. [{apiserver, cuttlefish:conf_get("cluster.k8s.apiserver", Conf)},
  124. {service_name, cuttlefish:conf_get("cluster.k8s.service_name", Conf)},
  125. {address_type, cuttlefish:conf_get("cluster.k8s.address_type", Conf, ip)},
  126. {app_name, cuttlefish:conf_get("cluster.k8s.app_name", Conf)}];
  127. (manual) ->
  128. [ ]
  129. end,
  130. {Strategy, Filter(Options(Strategy))}
  131. end}.
  132. %%--------------------------------------------------------------------
  133. %% Erlang Node
  134. %%--------------------------------------------------------------------
  135. %% @doc Erlang node name
  136. {mapping, "node.name", "vm_args.-name", [
  137. {default, "emq@127.0.0.1"}
  138. ]}.
  139. %% @doc Secret cookie for distributed erlang node
  140. {mapping, "node.cookie", "vm_args.-setcookie", [
  141. {default, "emqsecretcookie"}
  142. ]}.
  143. %% @doc SMP Support
  144. {mapping, "node.smp", "vm_args.-smp", [
  145. {default, auto},
  146. {datatype, {enum, [enable, auto, disable]}},
  147. hidden
  148. ]}.
  149. %% @doc http://erlang.org/doc/man/heart.html
  150. {mapping, "node.heartbeat", "vm_args.-heart", [
  151. {datatype, flag},
  152. hidden
  153. ]}.
  154. {translation, "vm_args.-heart", fun(Conf) ->
  155. case cuttlefish:conf_get("node.heartbeat", Conf) of
  156. true -> "";
  157. false -> cuttlefish:invalid("should be 'on' or comment the line!")
  158. end
  159. end}.
  160. %% @doc Enable Kernel Poll
  161. {mapping, "node.kernel_poll", "vm_args.+K", [
  162. {default, on},
  163. {datatype, flag},
  164. hidden
  165. ]}.
  166. %% @doc More information at: http://erlang.org/doc/man/erl.html
  167. {mapping, "node.async_threads", "vm_args.+A", [
  168. {default, 64},
  169. {datatype, integer},
  170. {validators, ["range:0-1024"]}
  171. ]}.
  172. %% @doc Erlang Process Limit
  173. {mapping, "node.process_limit", "vm_args.+P", [
  174. {datatype, integer},
  175. {default, 256000},
  176. hidden
  177. ]}.
  178. %% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q
  179. %% @doc The number of concurrent ports/sockets
  180. %% Valid range is 1024-134217727
  181. {mapping, "node.max_ports",
  182. cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [
  183. {default, 262144},
  184. {datatype, integer},
  185. {validators, ["range4ports"]}
  186. ]}.
  187. {validator, "range4ports", "must be 1024 to 134217727",
  188. fun(X) -> X >= 1024 andalso X =< 134217727 end}.
  189. %% @doc http://www.erlang.org/doc/man/erl.html#%2bzdbbl
  190. {mapping, "node.dist_buffer_size", "vm_args.+zdbbl", [
  191. {datatype, bytesize},
  192. {commented, "32MB"},
  193. hidden,
  194. {validators, ["zdbbl_range"]}
  195. ]}.
  196. {translation, "vm_args.+zdbbl",
  197. fun(Conf) ->
  198. ZDBBL = cuttlefish:conf_get("node.dist_buffer_size", Conf, undefined),
  199. case ZDBBL of
  200. undefined -> undefined;
  201. X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes;
  202. _ -> undefined
  203. end
  204. end
  205. }.
  206. {validator, "zdbbl_range", "must be between 1KB and 2097151KB",
  207. fun(ZDBBL) ->
  208. %% 2097151KB = 2147482624
  209. ZDBBL >= 1024 andalso ZDBBL =< 2147482624
  210. end
  211. }.
  212. %% @doc http://www.erlang.org/doc/man/erlang.html#system_flag-2
  213. {mapping, "node.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [
  214. {default, 1000},
  215. {datatype, integer},
  216. hidden,
  217. {validators, ["positive_integer"]}
  218. ]}.
  219. {validator, "positive_integer", "must be a positive integer",
  220. fun(X) -> X >= 0 end}.
  221. %% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES,
  222. %% R16+ uses +e
  223. %% @doc The ETS table limit
  224. {mapping, "node.max_ets_tables",
  225. cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [
  226. {default, 256000},
  227. {datatype, integer},
  228. hidden
  229. ]}.
  230. %% @doc Set the location of crash dumps
  231. {mapping, "node.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [
  232. {default, "{{crash_dump}}"},
  233. {datatype, file},
  234. hidden
  235. ]}.
  236. %% @doc http://www.erlang.org/doc/man/kernel_app.html#net_ticktime
  237. {mapping, "node.dist_net_ticktime", "vm_args.-kernel net_ticktime", [
  238. {commented, 60},
  239. {datatype, integer},
  240. hidden
  241. ]}.
  242. %% @doc http://www.erlang.org/doc/man/kernel_app.html
  243. {mapping, "node.dist_listen_min", "kernel.inet_dist_listen_min", [
  244. {commented, 6369},
  245. {datatype, integer},
  246. hidden
  247. ]}.
  248. %% @see node.dist_listen_min
  249. {mapping, "node.dist_listen_max", "kernel.inet_dist_listen_max", [
  250. {commented, 6369},
  251. {datatype, integer},
  252. hidden
  253. ]}.
  254. %%--------------------------------------------------------------------
  255. %% Log
  256. %%--------------------------------------------------------------------
  257. {mapping, "log.dir", "lager.log_dir", [
  258. {default, "log"},
  259. {datatype, string}
  260. ]}.
  261. {mapping, "log.console", "lager.handlers", [
  262. {default, file},
  263. {datatype, {enum, [off, file, console, both]}}
  264. ]}.
  265. {mapping, "log.console.level", "lager.handlers", [
  266. {default, info},
  267. {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}}
  268. ]}.
  269. {mapping, "log.console.file", "lager.handlers", [
  270. {default, "log/console.log"},
  271. {datatype, file}
  272. ]}.
  273. {mapping, "log.console.size", "lager.handlers", [
  274. {default, 10485760},
  275. {datatype, integer}
  276. ]}.
  277. {mapping, "log.console.count", "lager.handlers", [
  278. {default, 5},
  279. {datatype, integer}
  280. ]}.
  281. {mapping, "log.info.file", "lager.handlers", [
  282. {datatype, file}
  283. ]}.
  284. {mapping, "log.info.size", "lager.handlers", [
  285. {default, 10485760},
  286. {datatype, integer}
  287. ]}.
  288. {mapping, "log.info.count", "lager.handlers", [
  289. {default, 5},
  290. {datatype, integer}
  291. ]}.
  292. {mapping, "log.error.file", "lager.handlers", [
  293. {default, "log/error.log"},
  294. {datatype, file}
  295. ]}.
  296. {mapping, "log.error.size", "lager.handlers", [
  297. {default, 10485760},
  298. {datatype, integer}
  299. ]}.
  300. {mapping, "log.error.count", "lager.handlers", [
  301. {default, 5},
  302. {datatype, integer}
  303. ]}.
  304. {mapping, "log.syslog", "lager.handlers", [
  305. {default, off},
  306. {datatype, flag}
  307. ]}.
  308. {mapping, "log.syslog.identity", "lager.handlers", [
  309. {default, "emqttd"},
  310. {datatype, string}
  311. ]}.
  312. {mapping, "log.syslog.facility", "lager.handlers", [
  313. {default, local0},
  314. {datatype, {enum, [daemon, local0, local1, local2, local3, local4, local5, local6, local7]}}
  315. ]}.
  316. {mapping, "log.syslog.level", "lager.handlers", [
  317. {default, error},
  318. {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency]}}
  319. ]}.
  320. {mapping, "log.error.redirect", "lager.error_logger_redirect", [
  321. {default, on},
  322. {datatype, flag},
  323. hidden
  324. ]}.
  325. {mapping, "log.error.messages_per_second", "lager.error_logger_hwm", [
  326. {default, 1000},
  327. {datatype, integer},
  328. hidden
  329. ]}.
  330. {translation,
  331. "lager.handlers",
  332. fun(Conf) ->
  333. ErrorHandler = case cuttlefish:conf_get("log.error.file", Conf) of
  334. undefined -> [];
  335. ErrorFilename -> [{lager_file_backend, [{file, ErrorFilename},
  336. {level, error},
  337. {size, cuttlefish:conf_get("log.error.size", Conf)},
  338. {date, "$D0"},
  339. {count, cuttlefish:conf_get("log.error.count", Conf)}]}]
  340. end,
  341. InfoHandler = case cuttlefish:conf_get("log.info.file", Conf, undefined) of
  342. undefined -> [];
  343. InfoFilename -> [{lager_file_backend, [{file, InfoFilename},
  344. {level, info},
  345. {size, cuttlefish:conf_get("log.info.size", Conf)},
  346. {date, "$D0"},
  347. {count, cuttlefish:conf_get("log.info.count", Conf)}]}]
  348. end,
  349. ConsoleLogLevel = cuttlefish:conf_get("log.console.level", Conf),
  350. ConsoleLogFile = cuttlefish:conf_get("log.console.file", Conf),
  351. ConsoleHandler = {lager_console_backend, ConsoleLogLevel},
  352. ConsoleFileHandler = {lager_file_backend, [{file, ConsoleLogFile},
  353. {level, ConsoleLogLevel},
  354. {size, cuttlefish:conf_get("log.console.size", Conf)},
  355. {date, "$D0"},
  356. {count, cuttlefish:conf_get("log.console.count", Conf)}]},
  357. ConsoleHandlers = case cuttlefish:conf_get("log.console", Conf) of
  358. off -> [];
  359. file -> [ConsoleFileHandler];
  360. console -> [ConsoleHandler];
  361. both -> [ConsoleHandler, ConsoleFileHandler];
  362. _ -> []
  363. end,
  364. SyslogHandler = case cuttlefish:conf_get("log.syslog", Conf) of
  365. false -> [];
  366. true -> [{lager_syslog_backend,
  367. [cuttlefish:conf_get("log.syslog.identity", Conf),
  368. cuttlefish:conf_get("log.syslog.facility", Conf),
  369. cuttlefish:conf_get("log.syslog.level", Conf)]}]
  370. end,
  371. ConsoleHandlers ++ ErrorHandler ++ InfoHandler ++ SyslogHandler
  372. end
  373. }.
  374. {mapping, "log.crash", "lager.crash_log", [
  375. {default, on},
  376. {datatype, flag}
  377. ]}.
  378. {mapping, "log.crash.file", "lager.crash_log", [
  379. {default, "log/crash.log"},
  380. {datatype, file}
  381. ]}.
  382. {translation,
  383. "lager.crash_log",
  384. fun(Conf) ->
  385. case cuttlefish:conf_get("log.crash", Conf) of
  386. false -> undefined;
  387. _ ->
  388. cuttlefish:conf_get("log.crash.file", Conf, "./log/crash.log")
  389. end
  390. end}.
  391. {mapping, "sasl", "sasl.sasl_error_logger", [
  392. {default, off},
  393. {datatype, flag},
  394. hidden
  395. ]}.
  396. %%--------------------------------------------------------------------
  397. %% Allow Anonymous and Default ACL
  398. %%--------------------------------------------------------------------
  399. %% @doc Allow Anonymous
  400. {mapping, "mqtt.allow_anonymous", "emqttd.allow_anonymous", [
  401. {default, false},
  402. {datatype, {enum, [true, false]}}
  403. ]}.
  404. %% @doc ACL nomatch
  405. {mapping, "mqtt.acl_nomatch", "emqttd.acl_nomatch", [
  406. {default, allow},
  407. {datatype, {enum, [allow, deny]}}
  408. ]}.
  409. %% @doc Default ACL File
  410. {mapping, "mqtt.acl_file", "emqttd.acl_file", [
  411. {datatype, string},
  412. hidden
  413. ]}.
  414. %% @doc Cache ACL for PUBLISH
  415. {mapping, "mqtt.cache_acl", "emqttd.cache_acl", [
  416. {default, true},
  417. {datatype, {enum, [true, false]}}
  418. ]}.
  419. %%--------------------------------------------------------------------
  420. %% MQTT Protocol
  421. %%--------------------------------------------------------------------
  422. %% @doc Set the Max ClientId Length Allowed.
  423. {mapping, "mqtt.max_clientid_len", "emqttd.protocol", [
  424. {default, 1024},
  425. {datatype, integer}
  426. ]}.
  427. %% @doc Max Packet Size Allowed, 64K by default.
  428. {mapping, "mqtt.max_packet_size", "emqttd.protocol", [
  429. {default, "64KB"},
  430. {datatype, bytesize}
  431. ]}.
  432. %% @doc Keepalive backoff
  433. {mapping, "mqtt.keepalive_backoff", "emqttd.protocol", [
  434. {default, 1.25},
  435. {datatype, float}
  436. ]}.
  437. {translation, "emqttd.protocol", fun(Conf) ->
  438. [{max_clientid_len, cuttlefish:conf_get("mqtt.max_clientid_len", Conf)},
  439. {max_packet_size, cuttlefish:conf_get("mqtt.max_packet_size", Conf)},
  440. {keepalive_backoff, cuttlefish:conf_get("mqtt.keepalive_backoff", Conf)}]
  441. end}.
  442. {mapping, "mqtt.websocket_protocol_header", "emqttd.websocket_protocol_header", [
  443. {default, on},
  444. {datatype, flag}
  445. ]}.
  446. %%--------------------------------------------------------------------
  447. %% MQTT Connection
  448. %%--------------------------------------------------------------------
  449. %% @doc Force the client to GC: integer
  450. {mapping, "mqtt.conn.force_gc_count", "emqttd.conn_force_gc_count", [
  451. {datatype, integer}
  452. ]}.
  453. %%--------------------------------------------------------------------
  454. %% MQTT Client
  455. %%--------------------------------------------------------------------
  456. %% @doc Max Publish Rate of Message
  457. {mapping, "mqtt.client.max_publish_rate", "emqttd.client", [
  458. {default, 0},
  459. {datatype, integer}
  460. ]}.
  461. %% @doc Client Idle Timeout.
  462. {mapping, "mqtt.client.idle_timeout", "emqttd.client", [
  463. {default, "30s"},
  464. {datatype, {duration, ms}}
  465. ]}.
  466. %% @doc Enable Stats of Client.
  467. {mapping, "mqtt.client.enable_stats", "emqttd.client", [
  468. {default, off},
  469. {datatype, flag}
  470. ]}.
  471. {translation, "emqttd.client", fun(Conf) ->
  472. [{max_publish_rate, cuttlefish:conf_get("mqtt.client.max_publish_rate", Conf)},
  473. {client_idle_timeout, cuttlefish:conf_get("mqtt.client.idle_timeout", Conf)},
  474. {client_enable_stats, cuttlefish:conf_get("mqtt.client.enable_stats", Conf)}]
  475. end}.
  476. %%--------------------------------------------------------------------
  477. %% MQTT Session
  478. %%--------------------------------------------------------------------
  479. %% @doc Max Number of Subscriptions Allowed
  480. {mapping, "mqtt.session.max_subscriptions", "emqttd.session", [
  481. {default, 0},
  482. {datatype, integer}
  483. ]}.
  484. %% @doc Upgrade QoS?
  485. {mapping, "mqtt.session.upgrade_qos", "emqttd.session", [
  486. {default, off},
  487. {datatype, flag}
  488. ]}.
  489. %% @doc Max number of QoS 1 and 2 messages that can be “inflight” at one time.
  490. %% 0 means no limit
  491. {mapping, "mqtt.session.max_inflight", "emqttd.session", [
  492. {default, 100},
  493. {datatype, integer}
  494. ]}.
  495. %% @doc Retry interval for redelivering QoS1/2 messages.
  496. {mapping, "mqtt.session.retry_interval", "emqttd.session", [
  497. {default, "20s"},
  498. {datatype, {duration, ms}}
  499. ]}.
  500. %% @doc Max Packets that Awaiting PUBREL, 0 means no limit
  501. {mapping, "mqtt.session.max_awaiting_rel", "emqttd.session", [
  502. {default, 0},
  503. {datatype, integer}
  504. ]}.
  505. %% @doc Awaiting PUBREL Timeout
  506. {mapping, "mqtt.session.await_rel_timeout", "emqttd.session", [
  507. {default, "20s"},
  508. {datatype, {duration, ms}}
  509. ]}.
  510. %% @doc Enable Stats
  511. {mapping, "mqtt.session.enable_stats", "emqttd.session", [
  512. {default, off},
  513. {datatype, flag}
  514. ]}.
  515. %% @doc Session Expiry Interval
  516. {mapping, "mqtt.session.expiry_interval", "emqttd.session", [
  517. {default, "2h"},
  518. {datatype, {duration, ms}}
  519. ]}.
  520. %% @doc Ignore message from self publish
  521. {mapping, "mqtt.session.ignore_loop_deliver", "emqttd.session", [
  522. {default, false},
  523. {datatype, {enum, [true, false]}}
  524. ]}.
  525. {translation, "emqttd.session", fun(Conf) ->
  526. [{max_subscriptions, cuttlefish:conf_get("mqtt.session.max_subscriptions", Conf)},
  527. {upgrade_qos, cuttlefish:conf_get("mqtt.session.upgrade_qos", Conf)},
  528. {max_inflight, cuttlefish:conf_get("mqtt.session.max_inflight", Conf)},
  529. {retry_interval, cuttlefish:conf_get("mqtt.session.retry_interval", Conf)},
  530. {max_awaiting_rel, cuttlefish:conf_get("mqtt.session.max_awaiting_rel", Conf)},
  531. {await_rel_timeout, cuttlefish:conf_get("mqtt.session.await_rel_timeout", Conf)},
  532. {enable_stats, cuttlefish:conf_get("mqtt.session.enable_stats", Conf)},
  533. {expiry_interval, cuttlefish:conf_get("mqtt.session.expiry_interval", Conf)},
  534. {ignore_loop_deliver, cuttlefish:conf_get("mqtt.session.ignore_loop_deliver", Conf)}]
  535. end}.
  536. %%--------------------------------------------------------------------
  537. %% MQTT MQueue
  538. %%--------------------------------------------------------------------
  539. %% @doc Type: simple | priority
  540. {mapping, "mqtt.mqueue.type", "emqttd.mqueue", [
  541. {default, simple},
  542. {datatype, atom}
  543. ]}.
  544. %% @doc Topic Priority: 0~255, Default is 0
  545. {mapping, "mqtt.mqueue.priority", "emqttd.mqueue", [
  546. {default, ""},
  547. {datatype, string}
  548. ]}.
  549. %% @doc Max queue length. Enqueued messages when persistent client disconnected, or inflight window is full. 0 means no limit.
  550. {mapping, "mqtt.mqueue.max_length", "emqttd.mqueue", [
  551. {default, 0},
  552. {datatype, integer}
  553. ]}.
  554. %% @doc Low-water mark of queued messages
  555. {mapping, "mqtt.mqueue.low_watermark", "emqttd.mqueue", [
  556. {default, "20%"},
  557. {datatype, {percent, float}}
  558. ]}.
  559. %% @doc High-water mark of queued messages
  560. {mapping, "mqtt.mqueue.high_watermark", "emqttd.mqueue", [
  561. {default, "60%"},
  562. {datatype, {percent, float}}
  563. ]}.
  564. %% @doc Queue Qos0 messages?
  565. {mapping, "mqtt.mqueue.store_qos0", "emqttd.mqueue", [
  566. {default, true},
  567. {datatype, {enum, [true, false]}}
  568. ]}.
  569. {translation, "emqttd.mqueue", fun(Conf) ->
  570. Opts = [{type, cuttlefish:conf_get("mqtt.mqueue.type", Conf, simple)},
  571. {max_length, cuttlefish:conf_get("mqtt.mqueue.max_length", Conf)},
  572. {low_watermark, cuttlefish:conf_get("mqtt.mqueue.low_watermark", Conf)},
  573. {high_watermark, cuttlefish:conf_get("mqtt.mqueue.high_watermark", Conf)},
  574. {store_qos0, cuttlefish:conf_get("mqtt.mqueue.store_qos0", Conf)}],
  575. case cuttlefish:conf_get("mqtt.mqueue.priority", Conf) of
  576. undefined -> Opts;
  577. V -> [{priority,
  578. [begin [T, P] = string:tokens(S, "="),
  579. {T, list_to_integer(P)}
  580. end || S <- string:tokens(V, ",")]} | Opts]
  581. end
  582. end}.
  583. %%--------------------------------------------------------------------
  584. %% MQTT Broker
  585. %%--------------------------------------------------------------------
  586. {mapping, "mqtt.broker.sys_interval", "emqttd.broker_sys_interval", [
  587. {default, 60},
  588. {datatype, integer}
  589. ]}.
  590. %%--------------------------------------------------------------------
  591. %% MQTT PubSub
  592. %%--------------------------------------------------------------------
  593. {mapping, "mqtt.pubsub.pool_size", "emqttd.pubsub", [
  594. {default, 8},
  595. {datatype, integer}
  596. ]}.
  597. {mapping, "mqtt.pubsub.by_clientid", "emqttd.pubsub", [
  598. {default, true},
  599. {datatype, {enum, [true, false]}}
  600. ]}.
  601. {mapping, "mqtt.pubsub.async", "emqttd.pubsub", [
  602. {default, true},
  603. {datatype, {enum, [true, false]}}
  604. ]}.
  605. {translation, "emqttd.pubsub", fun(Conf) ->
  606. [{pool_size, cuttlefish:conf_get("mqtt.pubsub.pool_size", Conf)},
  607. {by_clientid, cuttlefish:conf_get("mqtt.pubsub.by_clientid", Conf)},
  608. {async, cuttlefish:conf_get("mqtt.pubsub.async", Conf)}]
  609. end}.
  610. %%--------------------------------------------------------------------
  611. %% MQTT Bridge
  612. %%--------------------------------------------------------------------
  613. {mapping, "mqtt.bridge.max_queue_len", "emqttd.bridge", [
  614. {default, 10000},
  615. {datatype, integer}
  616. ]}.
  617. {mapping, "mqtt.bridge.ping_down_interval", "emqttd.bridge", [
  618. {default, 1},
  619. {datatype, integer}
  620. ]}.
  621. {translation, "emqttd.bridge", fun(Conf) ->
  622. [{max_queue_len, cuttlefish:conf_get("mqtt.bridge.max_queue_len", Conf)},
  623. {ping_down_interval, cuttlefish:conf_get("mqtt.bridge.ping_down_interval", Conf)}]
  624. end}.
  625. %%-------------------------------------------------------------------
  626. %% MQTT Plugins
  627. %%-------------------------------------------------------------------
  628. {mapping, "mqtt.plugins.etc_dir", "emqttd.plugins_etc_dir", [
  629. {datatype, string}
  630. ]}.
  631. {mapping, "mqtt.plugins.loaded_file", "emqttd.plugins_loaded_file", [
  632. {datatype, string}
  633. ]}.
  634. %%--------------------------------------------------------------------
  635. %% MQTT Listeners
  636. %%--------------------------------------------------------------------
  637. %%--------------------------------------------------------------------
  638. %% TCP Listeners
  639. {mapping, "listener.tcp.$name", "emqttd.listeners", [
  640. {datatype, [integer, ip]}
  641. ]}.
  642. {mapping, "listener.tcp.$name.acceptors", "emqttd.listeners", [
  643. {default, 8},
  644. {datatype, integer}
  645. ]}.
  646. {mapping, "listener.tcp.$name.max_clients", "emqttd.listeners", [
  647. {default, 1024},
  648. {datatype, integer}
  649. ]}.
  650. {mapping, "listener.tcp.$name.zone", "emqttd.listeners", [
  651. {datatype, string}
  652. ]}.
  653. {mapping, "listener.tcp.$name.mountpoint", "emqttd.listeners", [
  654. {datatype, string}
  655. ]}.
  656. {mapping, "listener.tcp.$name.rate_limit", "emqttd.listeners", [
  657. {default, undefined},
  658. {datatype, string}
  659. ]}.
  660. {mapping, "listener.tcp.$name.access.$id", "emqttd.listeners", [
  661. {datatype, string}
  662. ]}.
  663. {mapping, "listener.tcp.$name.proxy_protocol", "emqttd.listeners", [
  664. %%{default, off},
  665. {datatype, flag}
  666. ]}.
  667. {mapping, "listener.tcp.$name.proxy_protocol_timeout", "emqttd.listeners", [
  668. %%{default, "5s"},
  669. {datatype, {duration, ms}}
  670. ]}.
  671. {mapping, "listener.tcp.$name.backlog", "emqttd.listeners", [
  672. {default, 1024},
  673. {datatype, integer}
  674. ]}.
  675. {mapping, "listener.tcp.$name.recbuf", "emqttd.listeners", [
  676. {datatype, bytesize},
  677. hidden
  678. ]}.
  679. {mapping, "listener.tcp.$name.sndbuf", "emqttd.listeners", [
  680. {datatype, bytesize},
  681. hidden
  682. ]}.
  683. {mapping, "listener.tcp.$name.buffer", "emqttd.listeners", [
  684. {datatype, bytesize},
  685. hidden
  686. ]}.
  687. {mapping, "listener.tcp.$name.tune_buffer", "emqttd.listeners", [
  688. {datatype, flag},
  689. hidden
  690. ]}.
  691. {mapping, "listener.tcp.$name.nodelay", "emqttd.listeners", [
  692. {datatype, {enum, [true, false]}},
  693. hidden
  694. ]}.
  695. %%--------------------------------------------------------------------
  696. %% SSL Listeners
  697. {mapping, "listener.ssl.$name", "emqttd.listeners", [
  698. {datatype, [integer, ip]}
  699. ]}.
  700. {mapping, "listener.ssl.$name.acceptors", "emqttd.listeners", [
  701. {default, 8},
  702. {datatype, integer}
  703. ]}.
  704. {mapping, "listener.ssl.$name.max_clients", "emqttd.listeners", [
  705. {default, 1024},
  706. {datatype, integer}
  707. ]}.
  708. {mapping, "listener.ssl.$name.zone", "emqttd.listeners", [
  709. {datatype, string}
  710. ]}.
  711. {mapping, "listener.ssl.$name.mountpoint", "emqttd.listeners", [
  712. {datatype, string}
  713. ]}.
  714. {mapping, "listener.ssl.$name.rate_limit", "emqttd.listeners", [
  715. {default, undefined},
  716. {datatype, string}
  717. ]}.
  718. {mapping, "listener.ssl.$name.access.$id", "emqttd.listeners", [
  719. {datatype, string}
  720. ]}.
  721. {mapping, "listener.ssl.$name.proxy_protocol", "emqttd.listeners", [
  722. %%{default, off},
  723. {datatype, flag}
  724. ]}.
  725. {mapping, "listener.ssl.$name.proxy_protocol_timeout", "emqttd.listeners", [
  726. %%{default, "5s"},
  727. {datatype, {duration, ms}}
  728. ]}.
  729. {mapping, "listener.ssl.$name.backlog", "emqttd.listeners", [
  730. {default, 1024},
  731. {datatype, integer}
  732. ]}.
  733. {mapping, "listener.ssl.$name.recbuf", "emqttd.listeners", [
  734. {datatype, bytesize},
  735. hidden
  736. ]}.
  737. {mapping, "listener.ssl.$name.sndbuf", "emqttd.listeners", [
  738. {datatype, bytesize},
  739. hidden
  740. ]}.
  741. {mapping, "listener.ssl.$name.buffer", "emqttd.listeners", [
  742. {datatype, bytesize},
  743. hidden
  744. ]}.
  745. {mapping, "listener.ssl.$name.tune_buffer", "emqttd.listeners", [
  746. {datatype, flag},
  747. hidden
  748. ]}.
  749. {mapping, "listener.ssl.$name.nodelay", "emqttd.listeners", [
  750. {datatype, {enum, [true, false]}},
  751. hidden
  752. ]}.
  753. {mapping, "listener.ssl.$name.tls_versions", "emqttd.listeners", [
  754. {datatype, string}
  755. ]}.
  756. {mapping, "listener.ssl.$name.ciphers", "emqttd.listeners", [
  757. {datatype, string}
  758. ]}.
  759. {mapping, "listener.ssl.$name.handshake_timeout", "emqttd.listeners", [
  760. {default, "15s"},
  761. {datatype, {duration, ms}}
  762. ]}.
  763. {mapping, "listener.ssl.$name.dhfile", "emqttd.listeners", [
  764. {datatype, string}
  765. ]}.
  766. {mapping, "listener.ssl.$name.keyfile", "emqttd.listeners", [
  767. {datatype, string}
  768. ]}.
  769. {mapping, "listener.ssl.$name.certfile", "emqttd.listeners", [
  770. {datatype, string}
  771. ]}.
  772. {mapping, "listener.ssl.$name.cacertfile", "emqttd.listeners", [
  773. {datatype, string}
  774. ]}.
  775. {mapping, "listener.ssl.$name.verify", "emqttd.listeners", [
  776. {datatype, atom}
  777. ]}.
  778. {mapping, "listener.ssl.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  779. {datatype, {enum, [true, false]}}
  780. ]}.
  781. {mapping, "listener.ssl.$name.secure_renegotiate", "emqttd.listeners", [
  782. {datatype, flag}
  783. ]}.
  784. {mapping, "listener.ssl.$name.reuse_sessions", "emqttd.listeners", [
  785. {default, on},
  786. {datatype, flag}
  787. ]}.
  788. {mapping, "listener.ssl.$name.honor_cipher_order", "emqttd.listeners", [
  789. {datatype, flag}
  790. ]}.
  791. {mapping, "listener.ssl.$name.peer_cert_as_username", "emqttd.listeners", [
  792. {datatype, {enum, [cn, dn]}}
  793. ]}.
  794. %%--------------------------------------------------------------------
  795. %% MQTT/WebSocket Listeners
  796. {mapping, "listener.ws.$name", "emqttd.listeners", [
  797. {datatype, [integer, ip]}
  798. ]}.
  799. {mapping, "listener.ws.$name.acceptors", "emqttd.listeners", [
  800. {default, 8},
  801. {datatype, integer}
  802. ]}.
  803. {mapping, "listener.ws.$name.max_clients", "emqttd.listeners", [
  804. {default, 1024},
  805. {datatype, integer}
  806. ]}.
  807. {mapping, "listener.ws.$name.rate_limit", "emqttd.listeners", [
  808. {datatype, string}
  809. ]}.
  810. {mapping, "listener.ws.$name.zone", "emqttd.listeners", [
  811. {datatype, string}
  812. ]}.
  813. {mapping, "listener.ws.$name.access.$id", "emqttd.listeners", [
  814. {datatype, string}
  815. ]}.
  816. {mapping, "listener.ws.$name.backlog", "emqttd.listeners", [
  817. {default, 1024},
  818. {datatype, integer}
  819. ]}.
  820. {mapping, "listener.ws.$name.recbuf", "emqttd.listeners", [
  821. {datatype, bytesize},
  822. hidden
  823. ]}.
  824. {mapping, "listener.ws.$name.sndbuf", "emqttd.listeners", [
  825. {datatype, bytesize},
  826. hidden
  827. ]}.
  828. {mapping, "listener.ws.$name.buffer", "emqttd.listeners", [
  829. {datatype, bytesize},
  830. hidden
  831. ]}.
  832. {mapping, "listener.ws.$name.tune_buffer", "emqttd.listeners", [
  833. {datatype, flag},
  834. hidden
  835. ]}.
  836. {mapping, "listener.ws.$name.nodelay", "emqttd.listeners", [
  837. {datatype, {enum, [true, false]}},
  838. hidden
  839. ]}.
  840. %%--------------------------------------------------------------------
  841. %% MQTT/WebSocket/SSL Listeners
  842. {mapping, "listener.wss.$name", "emqttd.listeners", [
  843. {datatype, [integer, ip]}
  844. ]}.
  845. {mapping, "listener.wss.$name.acceptors", "emqttd.listeners", [
  846. {default, 8},
  847. {datatype, integer}
  848. ]}.
  849. {mapping, "listener.wss.$name.max_clients", "emqttd.listeners", [
  850. {default, 1024},
  851. {datatype, integer}
  852. ]}.
  853. {mapping, "listener.wss.$name.zone", "emqttd.listeners", [
  854. {datatype, string}
  855. ]}.
  856. {mapping, "listener.wss.$name.mountpoint", "emqttd.listeners", [
  857. {datatype, string}
  858. ]}.
  859. {mapping, "listener.wss.$name.rate_limit", "emqttd.listeners", [
  860. {datatype, string}
  861. ]}.
  862. {mapping, "listener.wss.$name.access.$id", "emqttd.listeners", [
  863. {datatype, string}
  864. ]}.
  865. {mapping, "listener.wss.$name.backlog", "emqttd.listeners", [
  866. {default, 1024},
  867. {datatype, integer}
  868. ]}.
  869. {mapping, "listener.wss.$name.recbuf", "emqttd.listeners", [
  870. {datatype, bytesize},
  871. hidden
  872. ]}.
  873. {mapping, "listener.wss.$name.sndbuf", "emqttd.listeners", [
  874. {datatype, bytesize},
  875. hidden
  876. ]}.
  877. {mapping, "listener.wss.$name.buffer", "emqttd.listeners", [
  878. {datatype, bytesize},
  879. hidden
  880. ]}.
  881. {mapping, "listener.wss.$name.tune_buffer", "emqttd.listeners", [
  882. {datatype, flag},
  883. hidden
  884. ]}.
  885. {mapping, "listener.wss.$name.nodelay", "emqttd.listeners", [
  886. {datatype, {enum, [true, false]}},
  887. hidden
  888. ]}.
  889. {mapping, "listener.wss.$name.handshake_timeout", "emqttd.listeners", [
  890. {default, "15s"},
  891. {datatype, {duration, ms}}
  892. ]}.
  893. {mapping, "listener.wss.$name.keyfile", "emqttd.listeners", [
  894. {datatype, string}
  895. ]}.
  896. {mapping, "listener.wss.$name.certfile", "emqttd.listeners", [
  897. {datatype, string}
  898. ]}.
  899. {mapping, "listener.wss.$name.cacertfile", "emqttd.listeners", [
  900. {datatype, string}
  901. ]}.
  902. {mapping, "listener.wss.$name.verify", "emqttd.listeners", [
  903. {datatype, atom}
  904. ]}.
  905. {mapping, "listener.wss.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  906. {datatype, {enum, [true, false]}}
  907. ]}.
  908. {translation, "emqttd.listeners", fun(Conf) ->
  909. Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
  910. Atom = fun(undefined) -> undefined; (S) -> list_to_atom(S) end,
  911. Access = fun(S) ->
  912. [A, CIDR] = string:tokens(S, " "),
  913. {list_to_atom(A), case CIDR of "all" -> all; _ -> CIDR end}
  914. end,
  915. AccOpts = fun(Prefix) ->
  916. case cuttlefish_variable:filter_by_prefix(Prefix ++ ".access", Conf) of
  917. [] -> [];
  918. Rules -> [{access, [Access(Rule) || {_, Rule} <- Rules]}]
  919. end
  920. end,
  921. MountPoint = fun(undefined) -> undefined; (S) -> list_to_binary(S) end,
  922. ConnOpts = fun(Prefix) ->
  923. Filter([{zone, Atom(cuttlefish:conf_get(Prefix ++ ".zone", Conf, undefined))},
  924. {rate_limit, cuttlefish:conf_get(Prefix ++ ".rate_limit", Conf, undefined)},
  925. {proxy_protocol, cuttlefish:conf_get(Prefix ++ ".proxy_protocol", Conf, undefined)},
  926. {proxy_protocol_timeout, cuttlefish:conf_get(Prefix ++ ".proxy_protocol_timeout", Conf, undefined)},
  927. {mountpoint, MountPoint(cuttlefish:conf_get(Prefix ++ ".mountpoint", Conf, undefined))},
  928. {peer_cert_as_username, cuttlefish:conf_get(Prefix ++ ".peer_cert_as_username", Conf, undefined)}])
  929. end,
  930. LisOpts = fun(Prefix) ->
  931. Filter([{acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)},
  932. {max_clients, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)},
  933. {tune_buffer, cuttlefish:conf_get(Prefix ++ ".tune_buffer", Conf, undefined)} | AccOpts(Prefix)])
  934. end,
  935. TcpOpts = fun(Prefix) ->
  936. Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},
  937. {recbuf, cuttlefish:conf_get(Prefix ++ ".recbuf", Conf, undefined)},
  938. {sndbuf, cuttlefish:conf_get(Prefix ++ ".sndbuf", Conf, undefined)},
  939. {buffer, cuttlefish:conf_get(Prefix ++ ".buffer", Conf, undefined)},
  940. {nodelay, cuttlefish:conf_get(Prefix ++ ".nodelay", Conf, true)}])
  941. end,
  942. SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
  943. SslOpts = fun(Prefix) ->
  944. Versions = case SplitFun(cuttlefish:conf_get(Prefix ++ ".tls_versions", Conf, undefined)) of
  945. undefined -> undefined;
  946. L -> [list_to_atom(V) || V <- L]
  947. end,
  948. Filter([{versions, Versions},
  949. {ciphers, SplitFun(cuttlefish:conf_get(Prefix ++ ".ciphers", Conf, undefined))},
  950. {handshake_timeout, cuttlefish:conf_get(Prefix ++ ".handshake_timeout", Conf, undefined)},
  951. {dhfile, cuttlefish:conf_get(Prefix ++ ".dhfile", Conf, undefined)},
  952. {keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
  953. {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
  954. {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
  955. {verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
  956. {fail_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".fail_if_no_peer_cert", Conf, undefined)},
  957. {secure_renegotiate, cuttlefish:conf_get(Prefix ++ ".secure_renegotiate", Conf, undefined)},
  958. {reuse_sessions, cuttlefish:conf_get(Prefix ++ ".reuse_sessions", Conf, undefined)},
  959. {honor_cipher_order, cuttlefish:conf_get(Prefix ++ ".honor_cipher_order", Conf, undefined)}])
  960. end,
  961. TcpListeners = fun(Type, Name) ->
  962. Prefix = string:join(["listener", Type, Name], "."),
  963. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  964. undefined ->
  965. [];
  966. ListenOn ->
  967. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)}, {sockopts, TcpOpts(Prefix)} | LisOpts(Prefix)]}]
  968. end
  969. end,
  970. SslListeners = fun(Type, Name) ->
  971. Prefix = string:join(["listener", Type, Name], "."),
  972. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  973. undefined ->
  974. [];
  975. ListenOn ->
  976. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)},
  977. {sockopts, TcpOpts(Prefix)},
  978. {sslopts, SslOpts(Prefix)} | LisOpts(Prefix)]}]
  979. end
  980. end,
  981. ApiListeners = fun(Type, Name) ->
  982. Prefix = string:join(["listener", Type, Name], "."),
  983. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  984. undefined ->
  985. [];
  986. ListenOn ->
  987. SslOpts1 = case SslOpts(Prefix) of
  988. [] -> [];
  989. SslOpts0 -> [{sslopts, SslOpts0}]
  990. end,
  991. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)},
  992. {sockopts, TcpOpts(Prefix)}| LisOpts(Prefix)] ++ SslOpts1}]
  993. end
  994. end,
  995. lists:flatten([TcpListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  996. <- cuttlefish_variable:filter_by_prefix("listener.tcp", Conf)
  997. ++ cuttlefish_variable:filter_by_prefix("listener.ws", Conf)]
  998. ++
  999. [SslListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  1000. <- cuttlefish_variable:filter_by_prefix("listener.ssl", Conf)
  1001. ++ cuttlefish_variable:filter_by_prefix("listener.wss", Conf)]
  1002. ++
  1003. [ApiListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  1004. <- cuttlefish_variable:filter_by_prefix("listener.api", Conf)])
  1005. end}.
  1006. %%--------------------------------------------------------------------
  1007. %% MQTT REST API Listeners
  1008. {mapping, "listener.api.$name", "emqttd.listeners", [
  1009. {datatype, [integer, ip]}
  1010. ]}.
  1011. {mapping, "listener.api.$name.acceptors", "emqttd.listeners", [
  1012. {default, 8},
  1013. {datatype, integer}
  1014. ]}.
  1015. {mapping, "listener.api.$name.max_clients", "emqttd.listeners", [
  1016. {default, 1024},
  1017. {datatype, integer}
  1018. ]}.
  1019. {mapping, "listener.api.$name.rate_limit", "emqttd.listeners", [
  1020. {datatype, string}
  1021. ]}.
  1022. {mapping, "listener.api.$name.access.$id", "emqttd.listeners", [
  1023. {datatype, string}
  1024. ]}.
  1025. {mapping, "listener.api.$name.backlog", "emqttd.listeners", [
  1026. {default, 1024},
  1027. {datatype, integer}
  1028. ]}.
  1029. {mapping, "listener.api.$name.recbuf", "emqttd.listeners", [
  1030. {datatype, bytesize},
  1031. hidden
  1032. ]}.
  1033. {mapping, "listener.api.$name.sndbuf", "emqttd.listeners", [
  1034. {datatype, bytesize},
  1035. hidden
  1036. ]}.
  1037. {mapping, "listener.api.$name.buffer", "emqttd.listeners", [
  1038. {datatype, bytesize},
  1039. hidden
  1040. ]}.
  1041. {mapping, "listener.api.$name.tune_buffer", "emqttd.listeners", [
  1042. {datatype, flag},
  1043. hidden
  1044. ]}.
  1045. {mapping, "listener.api.$name.nodelay", "emqttd.listeners", [
  1046. {datatype, {enum, [true, false]}},
  1047. hidden
  1048. ]}.
  1049. {mapping, "listener.api.$name.handshake_timeout", "emqttd.listeners", [
  1050. {datatype, {duration, ms}}
  1051. ]}.
  1052. {mapping, "listener.api.$name.keyfile", "emqttd.listeners", [
  1053. {datatype, string}
  1054. ]}.
  1055. {mapping, "listener.api.$name.certfile", "emqttd.listeners", [
  1056. {datatype, string}
  1057. ]}.
  1058. {mapping, "listener.api.$name.cacertfile", "emqttd.listeners", [
  1059. {datatype, string}
  1060. ]}.
  1061. {mapping, "listener.api.$name.verify", "emqttd.listeners", [
  1062. {datatype, atom}
  1063. ]}.
  1064. {mapping, "listener.api.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  1065. {datatype, {enum, [true, false]}}
  1066. ]}.
  1067. %%--------------------------------------------------------------------
  1068. %% System Monitor
  1069. %%--------------------------------------------------------------------
  1070. %% @doc Long GC, don't monitor in production mode for:
  1071. %% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
  1072. {mapping, "sysmon.long_gc", "emqttd.sysmon", [
  1073. {default, false},
  1074. {datatype, {enum, [true, false]}}
  1075. ]}.
  1076. %% @doc Long Schedule(ms)
  1077. {mapping, "sysmon.long_schedule", "emqttd.sysmon", [
  1078. {default, 1000},
  1079. {datatype, integer}
  1080. ]}.
  1081. %% @doc Large Heap
  1082. {mapping, "sysmon.large_heap", "emqttd.sysmon", [
  1083. {default, "8MB"},
  1084. {datatype, bytesize}
  1085. ]}.
  1086. %% @doc Monitor Busy Port
  1087. {mapping, "sysmon.busy_port", "emqttd.sysmon", [
  1088. {default, false},
  1089. {datatype, {enum, [true, false]}}
  1090. ]}.
  1091. %% @doc Monitor Busy Dist Port
  1092. {mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [
  1093. {default, true},
  1094. {datatype, {enum, [true, false]}}
  1095. ]}.
  1096. {translation, "emqttd.sysmon", fun(Conf) ->
  1097. [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)},
  1098. {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)},
  1099. {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)},
  1100. {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)},
  1101. {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}]
  1102. end}.