emq.schema 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442
  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, undefined) 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. {datatype, {duration, ms}},
  588. {default, "1m"}
  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.async", "emqttd.pubsub", [
  598. {default, true},
  599. {datatype, {enum, [true, false]}}
  600. ]}.
  601. {translation, "emqttd.pubsub", fun(Conf) ->
  602. [{pool_size, cuttlefish:conf_get("mqtt.pubsub.pool_size", Conf)},
  603. {async, cuttlefish:conf_get("mqtt.pubsub.async", Conf)}]
  604. end}.
  605. %%--------------------------------------------------------------------
  606. %% MQTT Bridge
  607. %%--------------------------------------------------------------------
  608. {mapping, "mqtt.bridge.max_queue_len", "emqttd.bridge", [
  609. {default, 10000},
  610. {datatype, integer}
  611. ]}.
  612. {mapping, "mqtt.bridge.ping_down_interval", "emqttd.bridge", [
  613. {datatype, {duration, ms}},
  614. {default, "1s"}
  615. ]}.
  616. {translation, "emqttd.bridge", fun(Conf) ->
  617. [{max_queue_len, cuttlefish:conf_get("mqtt.bridge.max_queue_len", Conf)},
  618. {ping_down_interval, cuttlefish:conf_get("mqtt.bridge.ping_down_interval", Conf)}]
  619. end}.
  620. %%-------------------------------------------------------------------
  621. %% MQTT Plugins
  622. %%-------------------------------------------------------------------
  623. {mapping, "mqtt.plugins.etc_dir", "emqttd.plugins_etc_dir", [
  624. {datatype, string}
  625. ]}.
  626. {mapping, "mqtt.plugins.loaded_file", "emqttd.plugins_loaded_file", [
  627. {datatype, string}
  628. ]}.
  629. %%--------------------------------------------------------------------
  630. %% MQTT Listeners
  631. %%--------------------------------------------------------------------
  632. %%--------------------------------------------------------------------
  633. %% TCP Listeners
  634. {mapping, "listener.tcp.$name", "emqttd.listeners", [
  635. {datatype, [integer, ip]}
  636. ]}.
  637. {mapping, "listener.tcp.$name.acceptors", "emqttd.listeners", [
  638. {default, 8},
  639. {datatype, integer}
  640. ]}.
  641. {mapping, "listener.tcp.$name.max_clients", "emqttd.listeners", [
  642. {default, 1024},
  643. {datatype, integer}
  644. ]}.
  645. {mapping, "listener.tcp.$name.zone", "emqttd.listeners", [
  646. {datatype, string}
  647. ]}.
  648. {mapping, "listener.tcp.$name.mountpoint", "emqttd.listeners", [
  649. {datatype, string}
  650. ]}.
  651. {mapping, "listener.tcp.$name.rate_limit", "emqttd.listeners", [
  652. {default, undefined},
  653. {datatype, string}
  654. ]}.
  655. {mapping, "listener.tcp.$name.access.$id", "emqttd.listeners", [
  656. {datatype, string}
  657. ]}.
  658. {mapping, "listener.tcp.$name.proxy_protocol", "emqttd.listeners", [
  659. {datatype, flag}
  660. ]}.
  661. {mapping, "listener.tcp.$name.proxy_protocol_timeout", "emqttd.listeners", [
  662. {datatype, {duration, ms}}
  663. ]}.
  664. {mapping, "listener.tcp.$name.peer_cert_as_username", "emqttd.listeners", [
  665. {datatype, {enum, [cn, dn]}}
  666. ]}.
  667. {mapping, "listener.tcp.$name.backlog", "emqttd.listeners", [
  668. {datatype, integer},
  669. {default, 1024}
  670. ]}.
  671. {mapping, "listener.tcp.$name.send_timeout", "emqttd.listeners", [
  672. {datatype, {duration, ms}},
  673. {default, "15s"}
  674. ]}.
  675. {mapping, "listener.tcp.$name.send_timeout_close", "emqttd.listeners", [
  676. {datatype, flag},
  677. {default, on}
  678. ]}.
  679. {mapping, "listener.tcp.$name.recbuf", "emqttd.listeners", [
  680. {datatype, bytesize},
  681. hidden
  682. ]}.
  683. {mapping, "listener.tcp.$name.sndbuf", "emqttd.listeners", [
  684. {datatype, bytesize},
  685. hidden
  686. ]}.
  687. {mapping, "listener.tcp.$name.buffer", "emqttd.listeners", [
  688. {datatype, bytesize},
  689. hidden
  690. ]}.
  691. {mapping, "listener.tcp.$name.tune_buffer", "emqttd.listeners", [
  692. {datatype, flag},
  693. hidden
  694. ]}.
  695. {mapping, "listener.tcp.$name.nodelay", "emqttd.listeners", [
  696. {datatype, {enum, [true, false]}},
  697. hidden
  698. ]}.
  699. %%--------------------------------------------------------------------
  700. %% SSL Listeners
  701. {mapping, "listener.ssl.$name", "emqttd.listeners", [
  702. {datatype, [integer, ip]}
  703. ]}.
  704. {mapping, "listener.ssl.$name.acceptors", "emqttd.listeners", [
  705. {default, 8},
  706. {datatype, integer}
  707. ]}.
  708. {mapping, "listener.ssl.$name.max_clients", "emqttd.listeners", [
  709. {default, 1024},
  710. {datatype, integer}
  711. ]}.
  712. {mapping, "listener.ssl.$name.zone", "emqttd.listeners", [
  713. {datatype, string}
  714. ]}.
  715. {mapping, "listener.ssl.$name.mountpoint", "emqttd.listeners", [
  716. {datatype, string}
  717. ]}.
  718. {mapping, "listener.ssl.$name.rate_limit", "emqttd.listeners", [
  719. {default, undefined},
  720. {datatype, string}
  721. ]}.
  722. {mapping, "listener.ssl.$name.access.$id", "emqttd.listeners", [
  723. {datatype, string}
  724. ]}.
  725. {mapping, "listener.ssl.$name.proxy_protocol", "emqttd.listeners", [
  726. {datatype, flag}
  727. ]}.
  728. {mapping, "listener.ssl.$name.proxy_protocol_timeout", "emqttd.listeners", [
  729. {datatype, {duration, ms}}
  730. ]}.
  731. {mapping, "listener.ssl.$name.backlog", "emqttd.listeners", [
  732. {default, 1024},
  733. {datatype, integer}
  734. ]}.
  735. {mapping, "listener.ssl.$name.send_timeout", "emqttd.listeners", [
  736. {datatype, {duration, ms}},
  737. {default, "15s"}
  738. ]}.
  739. {mapping, "listener.ssl.$name.send_timeout_close", "emqttd.listeners", [
  740. {datatype, flag},
  741. {default, on}
  742. ]}.
  743. {mapping, "listener.ssl.$name.recbuf", "emqttd.listeners", [
  744. {datatype, bytesize},
  745. hidden
  746. ]}.
  747. {mapping, "listener.ssl.$name.sndbuf", "emqttd.listeners", [
  748. {datatype, bytesize},
  749. hidden
  750. ]}.
  751. {mapping, "listener.ssl.$name.buffer", "emqttd.listeners", [
  752. {datatype, bytesize},
  753. hidden
  754. ]}.
  755. {mapping, "listener.ssl.$name.tune_buffer", "emqttd.listeners", [
  756. {datatype, flag},
  757. hidden
  758. ]}.
  759. {mapping, "listener.ssl.$name.nodelay", "emqttd.listeners", [
  760. {datatype, {enum, [true, false]}},
  761. hidden
  762. ]}.
  763. {mapping, "listener.ssl.$name.tls_versions", "emqttd.listeners", [
  764. {datatype, string}
  765. ]}.
  766. {mapping, "listener.ssl.$name.ciphers", "emqttd.listeners", [
  767. {datatype, string}
  768. ]}.
  769. {mapping, "listener.ssl.$name.handshake_timeout", "emqttd.listeners", [
  770. {default, "15s"},
  771. {datatype, {duration, ms}}
  772. ]}.
  773. {mapping, "listener.ssl.$name.dhfile", "emqttd.listeners", [
  774. {datatype, string}
  775. ]}.
  776. {mapping, "listener.ssl.$name.keyfile", "emqttd.listeners", [
  777. {datatype, string}
  778. ]}.
  779. {mapping, "listener.ssl.$name.certfile", "emqttd.listeners", [
  780. {datatype, string}
  781. ]}.
  782. {mapping, "listener.ssl.$name.cacertfile", "emqttd.listeners", [
  783. {datatype, string}
  784. ]}.
  785. {mapping, "listener.ssl.$name.verify", "emqttd.listeners", [
  786. {datatype, atom}
  787. ]}.
  788. {mapping, "listener.ssl.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  789. {datatype, {enum, [true, false]}}
  790. ]}.
  791. {mapping, "listener.ssl.$name.secure_renegotiate", "emqttd.listeners", [
  792. {datatype, flag}
  793. ]}.
  794. {mapping, "listener.ssl.$name.reuse_sessions", "emqttd.listeners", [
  795. {default, on},
  796. {datatype, flag}
  797. ]}.
  798. {mapping, "listener.ssl.$name.honor_cipher_order", "emqttd.listeners", [
  799. {datatype, flag}
  800. ]}.
  801. {mapping, "listener.ssl.$name.peer_cert_as_username", "emqttd.listeners", [
  802. {datatype, {enum, [cn, dn]}}
  803. ]}.
  804. %%--------------------------------------------------------------------
  805. %% MQTT/WebSocket Listeners
  806. {mapping, "listener.ws.$name", "emqttd.listeners", [
  807. {datatype, [integer, ip]}
  808. ]}.
  809. {mapping, "listener.ws.$name.acceptors", "emqttd.listeners", [
  810. {default, 8},
  811. {datatype, integer}
  812. ]}.
  813. {mapping, "listener.ws.$name.max_clients", "emqttd.listeners", [
  814. {default, 1024},
  815. {datatype, integer}
  816. ]}.
  817. {mapping, "listener.ws.$name.rate_limit", "emqttd.listeners", [
  818. {datatype, string}
  819. ]}.
  820. {mapping, "listener.ws.$name.zone", "emqttd.listeners", [
  821. {datatype, string}
  822. ]}.
  823. {mapping, "listener.ws.$name.mountpoint", "emqttd.listeners", [
  824. {datatype, string}
  825. ]}.
  826. {mapping, "listener.ws.$name.access.$id", "emqttd.listeners", [
  827. {datatype, string}
  828. ]}.
  829. {mapping, "listener.ws.$name.proxy_protocol", "emqttd.listeners", [
  830. {datatype, flag}
  831. ]}.
  832. {mapping, "listener.ws.$name.proxy_protocol_timeout", "emqttd.listeners", [
  833. {datatype, {duration, ms}}
  834. ]}.
  835. {mapping, "listener.ws.$name.backlog", "emqttd.listeners", [
  836. {default, 1024},
  837. {datatype, integer}
  838. ]}.
  839. {mapping, "listener.ws.$name.send_timeout", "emqttd.listeners", [
  840. {datatype, {duration, ms}},
  841. {default, "15s"}
  842. ]}.
  843. {mapping, "listener.ws.$name.send_timeout_close", "emqttd.listeners", [
  844. {datatype, flag},
  845. {default, on}
  846. ]}.
  847. {mapping, "listener.ws.$name.recbuf", "emqttd.listeners", [
  848. {datatype, bytesize},
  849. hidden
  850. ]}.
  851. {mapping, "listener.ws.$name.sndbuf", "emqttd.listeners", [
  852. {datatype, bytesize},
  853. hidden
  854. ]}.
  855. {mapping, "listener.ws.$name.buffer", "emqttd.listeners", [
  856. {datatype, bytesize},
  857. hidden
  858. ]}.
  859. {mapping, "listener.ws.$name.tune_buffer", "emqttd.listeners", [
  860. {datatype, flag},
  861. hidden
  862. ]}.
  863. {mapping, "listener.ws.$name.nodelay", "emqttd.listeners", [
  864. {datatype, {enum, [true, false]}},
  865. hidden
  866. ]}.
  867. %%--------------------------------------------------------------------
  868. %% MQTT/WebSocket/SSL Listeners
  869. {mapping, "listener.wss.$name", "emqttd.listeners", [
  870. {datatype, [integer, ip]}
  871. ]}.
  872. {mapping, "listener.wss.$name.acceptors", "emqttd.listeners", [
  873. {default, 8},
  874. {datatype, integer}
  875. ]}.
  876. {mapping, "listener.wss.$name.max_clients", "emqttd.listeners", [
  877. {default, 1024},
  878. {datatype, integer}
  879. ]}.
  880. {mapping, "listener.wss.$name.zone", "emqttd.listeners", [
  881. {datatype, string}
  882. ]}.
  883. {mapping, "listener.wss.$name.mountpoint", "emqttd.listeners", [
  884. {datatype, string}
  885. ]}.
  886. {mapping, "listener.wss.$name.rate_limit", "emqttd.listeners", [
  887. {datatype, string}
  888. ]}.
  889. {mapping, "listener.wss.$name.access.$id", "emqttd.listeners", [
  890. {datatype, string}
  891. ]}.
  892. {mapping, "listener.wss.$name.proxy_protocol", "emqttd.listeners", [
  893. {datatype, flag}
  894. ]}.
  895. {mapping, "listener.wss.$name.proxy_protocol_timeout", "emqttd.listeners", [
  896. {datatype, {duration, ms}}
  897. ]}.
  898. {mapping, "listener.wss.$name.backlog", "emqttd.listeners", [
  899. {default, 1024},
  900. {datatype, integer}
  901. ]}.
  902. {mapping, "listener.wss.$name.send_timeout", "emqttd.listeners", [
  903. {datatype, {duration, ms}},
  904. {default, "15s"}
  905. ]}.
  906. {mapping, "listener.wss.$name.send_timeout_close", "emqttd.listeners", [
  907. {datatype, flag},
  908. {default, on}
  909. ]}.
  910. {mapping, "listener.wss.$name.recbuf", "emqttd.listeners", [
  911. {datatype, bytesize},
  912. hidden
  913. ]}.
  914. {mapping, "listener.wss.$name.sndbuf", "emqttd.listeners", [
  915. {datatype, bytesize},
  916. hidden
  917. ]}.
  918. {mapping, "listener.wss.$name.buffer", "emqttd.listeners", [
  919. {datatype, bytesize},
  920. hidden
  921. ]}.
  922. {mapping, "listener.wss.$name.tune_buffer", "emqttd.listeners", [
  923. {datatype, flag},
  924. hidden
  925. ]}.
  926. {mapping, "listener.wss.$name.nodelay", "emqttd.listeners", [
  927. {datatype, {enum, [true, false]}},
  928. hidden
  929. ]}.
  930. {mapping, "listener.wss.$name.tls_versions", "emqttd.listeners", [
  931. {datatype, string}
  932. ]}.
  933. {mapping, "listener.wss.$name.ciphers", "emqttd.listeners", [
  934. {datatype, string}
  935. ]}.
  936. {mapping, "listener.wss.$name.handshake_timeout", "emqttd.listeners", [
  937. {default, "15s"},
  938. {datatype, {duration, ms}}
  939. ]}.
  940. {mapping, "listener.wss.$name.keyfile", "emqttd.listeners", [
  941. {datatype, string}
  942. ]}.
  943. {mapping, "listener.wss.$name.certfile", "emqttd.listeners", [
  944. {datatype, string}
  945. ]}.
  946. {mapping, "listener.wss.$name.cacertfile", "emqttd.listeners", [
  947. {datatype, string}
  948. ]}.
  949. {mapping, "listener.wss.$name.verify", "emqttd.listeners", [
  950. {datatype, atom}
  951. ]}.
  952. {mapping, "listener.wss.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  953. {datatype, {enum, [true, false]}}
  954. ]}.
  955. {mapping, "listener.wss.$name.secure_renegotiate", "emqttd.listeners", [
  956. {datatype, flag}
  957. ]}.
  958. {mapping, "listener.wss.$name.reuse_sessions", "emqttd.listeners", [
  959. {default, on},
  960. {datatype, flag}
  961. ]}.
  962. {mapping, "listener.wss.$name.honor_cipher_order", "emqttd.listeners", [
  963. {datatype, flag}
  964. ]}.
  965. {mapping, "listener.wss.$name.peer_cert_as_username", "emqttd.listeners", [
  966. {datatype, {enum, [cn, dn]}}
  967. ]}.
  968. {translation, "emqttd.listeners", fun(Conf) ->
  969. Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
  970. Atom = fun(undefined) -> undefined; (S) -> list_to_atom(S) end,
  971. Access = fun(S) ->
  972. [A, CIDR] = string:tokens(S, " "),
  973. {list_to_atom(A), case CIDR of "all" -> all; _ -> CIDR end}
  974. end,
  975. AccOpts = fun(Prefix) ->
  976. case cuttlefish_variable:filter_by_prefix(Prefix ++ ".access", Conf) of
  977. [] -> [];
  978. Rules -> [{access, [Access(Rule) || {_, Rule} <- Rules]}]
  979. end
  980. end,
  981. MountPoint = fun(undefined) -> undefined; (S) -> list_to_binary(S) end,
  982. ConnOpts = fun(Prefix) ->
  983. Filter([{zone, Atom(cuttlefish:conf_get(Prefix ++ ".zone", Conf, undefined))},
  984. {rate_limit, cuttlefish:conf_get(Prefix ++ ".rate_limit", Conf, undefined)},
  985. {proxy_protocol, cuttlefish:conf_get(Prefix ++ ".proxy_protocol", Conf, undefined)},
  986. {proxy_protocol_timeout, cuttlefish:conf_get(Prefix ++ ".proxy_protocol_timeout", Conf, undefined)},
  987. {mountpoint, MountPoint(cuttlefish:conf_get(Prefix ++ ".mountpoint", Conf, undefined))},
  988. {peer_cert_as_username, cuttlefish:conf_get(Prefix ++ ".peer_cert_as_username", Conf, undefined)}])
  989. end,
  990. LisOpts = fun(Prefix) ->
  991. Filter([{acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)},
  992. {max_clients, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)},
  993. {tune_buffer, cuttlefish:conf_get(Prefix ++ ".tune_buffer", Conf, undefined)} | AccOpts(Prefix)])
  994. end,
  995. TcpOpts = fun(Prefix) ->
  996. Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},
  997. {send_timeout, cuttlefish:conf_get(Prefix ++ ".send_timeout", Conf, undefined)},
  998. {send_timeout_close, cuttlefish:conf_get(Prefix ++ ".send_timeout_close", Conf, undefined)},
  999. {recbuf, cuttlefish:conf_get(Prefix ++ ".recbuf", Conf, undefined)},
  1000. {sndbuf, cuttlefish:conf_get(Prefix ++ ".sndbuf", Conf, undefined)},
  1001. {buffer, cuttlefish:conf_get(Prefix ++ ".buffer", Conf, undefined)},
  1002. {nodelay, cuttlefish:conf_get(Prefix ++ ".nodelay", Conf, true)}])
  1003. end,
  1004. SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
  1005. SslOpts = fun(Prefix) ->
  1006. Versions = case SplitFun(cuttlefish:conf_get(Prefix ++ ".tls_versions", Conf, undefined)) of
  1007. undefined -> undefined;
  1008. L -> [list_to_atom(V) || V <- L]
  1009. end,
  1010. Filter([{versions, Versions},
  1011. {ciphers, SplitFun(cuttlefish:conf_get(Prefix ++ ".ciphers", Conf, undefined))},
  1012. {handshake_timeout, cuttlefish:conf_get(Prefix ++ ".handshake_timeout", Conf, undefined)},
  1013. {dhfile, cuttlefish:conf_get(Prefix ++ ".dhfile", Conf, undefined)},
  1014. {keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
  1015. {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
  1016. {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
  1017. {verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
  1018. {fail_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".fail_if_no_peer_cert", Conf, undefined)},
  1019. {secure_renegotiate, cuttlefish:conf_get(Prefix ++ ".secure_renegotiate", Conf, undefined)},
  1020. {reuse_sessions, cuttlefish:conf_get(Prefix ++ ".reuse_sessions", Conf, undefined)},
  1021. {honor_cipher_order, cuttlefish:conf_get(Prefix ++ ".honor_cipher_order", Conf, undefined)}])
  1022. end,
  1023. TcpListeners = fun(Type, Name) ->
  1024. Prefix = string:join(["listener", Type, Name], "."),
  1025. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  1026. undefined ->
  1027. [];
  1028. ListenOn ->
  1029. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)}, {sockopts, TcpOpts(Prefix)} | LisOpts(Prefix)]}]
  1030. end
  1031. end,
  1032. SslListeners = fun(Type, Name) ->
  1033. Prefix = string:join(["listener", Type, Name], "."),
  1034. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  1035. undefined ->
  1036. [];
  1037. ListenOn ->
  1038. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)},
  1039. {sockopts, TcpOpts(Prefix)},
  1040. {sslopts, SslOpts(Prefix)} | LisOpts(Prefix)]}]
  1041. end
  1042. end,
  1043. ApiListeners = fun(Type, Name) ->
  1044. Prefix = string:join(["listener", Type, Name], "."),
  1045. case cuttlefish:conf_get(Prefix, Conf, undefined) of
  1046. undefined ->
  1047. [];
  1048. ListenOn ->
  1049. SslOpts1 = case SslOpts(Prefix) of
  1050. [] -> [];
  1051. SslOpts0 -> [{sslopts, SslOpts0}]
  1052. end,
  1053. [{Atom(Type), ListenOn, [{connopts, ConnOpts(Prefix)},
  1054. {sockopts, TcpOpts(Prefix)}| LisOpts(Prefix)] ++ SslOpts1}]
  1055. end
  1056. end,
  1057. lists:flatten([TcpListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  1058. <- cuttlefish_variable:filter_by_prefix("listener.tcp", Conf)
  1059. ++ cuttlefish_variable:filter_by_prefix("listener.ws", Conf)]
  1060. ++
  1061. [SslListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  1062. <- cuttlefish_variable:filter_by_prefix("listener.ssl", Conf)
  1063. ++ cuttlefish_variable:filter_by_prefix("listener.wss", Conf)]
  1064. ++
  1065. [ApiListeners(Type, Name) || {["listener", Type, Name], ListenOn}
  1066. <- cuttlefish_variable:filter_by_prefix("listener.api", Conf)])
  1067. end}.
  1068. %%--------------------------------------------------------------------
  1069. %% MQTT REST API Listeners
  1070. {mapping, "listener.api.$name", "emqttd.listeners", [
  1071. {datatype, [integer, ip]}
  1072. ]}.
  1073. {mapping, "listener.api.$name.acceptors", "emqttd.listeners", [
  1074. {default, 8},
  1075. {datatype, integer}
  1076. ]}.
  1077. {mapping, "listener.api.$name.max_clients", "emqttd.listeners", [
  1078. {default, 1024},
  1079. {datatype, integer}
  1080. ]}.
  1081. {mapping, "listener.api.$name.rate_limit", "emqttd.listeners", [
  1082. {datatype, string}
  1083. ]}.
  1084. {mapping, "listener.api.$name.access.$id", "emqttd.listeners", [
  1085. {datatype, string}
  1086. ]}.
  1087. {mapping, "listener.api.$name.backlog", "emqttd.listeners", [
  1088. {default, 1024},
  1089. {datatype, integer}
  1090. ]}.
  1091. {mapping, "listener.api.$name.send_timeout", "emqttd.listeners", [
  1092. {datatype, {duration, ms}},
  1093. {default, "15s"}
  1094. ]}.
  1095. {mapping, "listener.api.$name.send_timeout_close", "emqttd.listeners", [
  1096. {datatype, flag},
  1097. {default, on}
  1098. ]}.
  1099. {mapping, "listener.api.$name.recbuf", "emqttd.listeners", [
  1100. {datatype, bytesize},
  1101. hidden
  1102. ]}.
  1103. {mapping, "listener.api.$name.sndbuf", "emqttd.listeners", [
  1104. {datatype, bytesize},
  1105. hidden
  1106. ]}.
  1107. {mapping, "listener.api.$name.buffer", "emqttd.listeners", [
  1108. {datatype, bytesize},
  1109. hidden
  1110. ]}.
  1111. {mapping, "listener.api.$name.tune_buffer", "emqttd.listeners", [
  1112. {datatype, flag},
  1113. hidden
  1114. ]}.
  1115. {mapping, "listener.api.$name.nodelay", "emqttd.listeners", [
  1116. {datatype, {enum, [true, false]}},
  1117. hidden
  1118. ]}.
  1119. {mapping, "listener.api.$name.handshake_timeout", "emqttd.listeners", [
  1120. {datatype, {duration, ms}}
  1121. ]}.
  1122. {mapping, "listener.api.$name.keyfile", "emqttd.listeners", [
  1123. {datatype, string}
  1124. ]}.
  1125. {mapping, "listener.api.$name.certfile", "emqttd.listeners", [
  1126. {datatype, string}
  1127. ]}.
  1128. {mapping, "listener.api.$name.cacertfile", "emqttd.listeners", [
  1129. {datatype, string}
  1130. ]}.
  1131. {mapping, "listener.api.$name.verify", "emqttd.listeners", [
  1132. {datatype, atom}
  1133. ]}.
  1134. {mapping, "listener.api.$name.fail_if_no_peer_cert", "emqttd.listeners", [
  1135. {datatype, {enum, [true, false]}}
  1136. ]}.
  1137. %%--------------------------------------------------------------------
  1138. %% System Monitor
  1139. %%--------------------------------------------------------------------
  1140. %% @doc Long GC, don't monitor in production mode for:
  1141. %% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
  1142. {mapping, "sysmon.long_gc", "emqttd.sysmon", [
  1143. {default, false},
  1144. {datatype, {enum, [true, false]}}
  1145. ]}.
  1146. %% @doc Long Schedule(ms)
  1147. {mapping, "sysmon.long_schedule", "emqttd.sysmon", [
  1148. {default, 1000},
  1149. {datatype, integer}
  1150. ]}.
  1151. %% @doc Large Heap
  1152. {mapping, "sysmon.large_heap", "emqttd.sysmon", [
  1153. {default, "8MB"},
  1154. {datatype, bytesize}
  1155. ]}.
  1156. %% @doc Monitor Busy Port
  1157. {mapping, "sysmon.busy_port", "emqttd.sysmon", [
  1158. {default, false},
  1159. {datatype, {enum, [true, false]}}
  1160. ]}.
  1161. %% @doc Monitor Busy Dist Port
  1162. {mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [
  1163. {default, true},
  1164. {datatype, {enum, [true, false]}}
  1165. ]}.
  1166. {translation, "emqttd.sysmon", fun(Conf) ->
  1167. [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)},
  1168. {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)},
  1169. {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)},
  1170. {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)},
  1171. {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}]
  1172. end}.