plugins.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. .. _plugins:
  2. =======
  3. Plugins
  4. =======
  5. The emqttd broker could be extended by plugins. Users could develop plugins to customize authentication, ACL and functions of the broker, or integrate the broker with other systems.
  6. The plugins that emqtt project released:
  7. +---------------------------+---------------------------+
  8. | Plugin | Description |
  9. +===========================+===========================+
  10. | `emqttd_plugin_template`_ | Template Plugin |
  11. +---------------------------+---------------------------+
  12. | `emqttd_dashboard`_ | Web Dashboard |
  13. +---------------------------+---------------------------+
  14. | `emqttd_plugin_mysql`_ | MySQL Auth/ACL Plugin |
  15. +---------------------------+---------------------------+
  16. | `emqttd_plugin_pgsql`_ | PostgreSQL Auth/ACL Plugin|
  17. +---------------------------+---------------------------+
  18. | `emqttd_plugin_redis`_ | Redis Auth/ACL Plugin |
  19. +---------------------------+---------------------------+
  20. | `emqttd_stomp`_ | STOMP Protocol Plugin |
  21. +---------------------------+---------------------------+
  22. | `emqttd_sockjs`_ | STOMP over SockJS Plugin |
  23. +---------------------------+---------------------------+
  24. | `emqttd_recon`_ | Recon Plugin |
  25. +---------------------------+---------------------------+
  26. ----------------------------------------
  27. emqttd_plugin_template - Template Plugin
  28. ----------------------------------------
  29. A plugin is just a normal Erlang application under the 'emqttd/plugins' folder. Each plugin has e configuration file: 'etc/plugin.config'.
  30. plugins/emqttd_plugin_template is a demo plugin. The folder structure:
  31. +------------------------+---------------------------+
  32. | File | Description |
  33. +========================+===========================+
  34. | etc/plugin.config | Plugin config file |
  35. +------------------------+---------------------------+
  36. | ebin/ | Erlang program files |
  37. +------------------------+---------------------------+
  38. Load, unload Plugin
  39. -------------------
  40. Use 'bin/emqttd_ctl plugins' CLI to load, unload a plugin::
  41. ./bin/emqttd_ctl plugins load <PluginName>
  42. ./bin/emqttd_ctl plugins unload <PluginName>
  43. ./bin/emqttd_ctl plugins list
  44. -----------------------------------
  45. emqttd_dashboard - Dashboard Plugin
  46. -----------------------------------
  47. The Web Dashboard for emqttd broker. The plugin will be loaded automatically when the broker started successfully.
  48. +------------------+---------------------------+
  49. | Address | http://localhost:18083 |
  50. +------------------+---------------------------+
  51. | Default User | admin |
  52. +------------------+---------------------------+
  53. | Default Password | public |
  54. +------------------+---------------------------+
  55. .. image:: _static/images/dashboard.png
  56. Configure Dashboard
  57. -------------------
  58. emqttd_dashboard/etc/plugin.config:
  59. .. code-block:: erlang
  60. [
  61. {emqttd_dashboard, [
  62. {default_admin, [
  63. {login, "admin"},
  64. {password, "public"}
  65. ]},
  66. {listener,
  67. {emqttd_dashboard, 18083, [
  68. {acceptors, 4},
  69. {max_clients, 512}]}
  70. }
  71. ]}
  72. ].
  73. -------------------------------------------
  74. emqttd_plugin_mysql - MySQL Auth/ACL Plugin
  75. -------------------------------------------
  76. MQTT Authentication, ACL with MySQL database.
  77. MQTT User Table
  78. ---------------
  79. .. code-block:: sql
  80. CREATE TABLE `mqtt_user` (
  81. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  82. `username` varchar(100) DEFAULT NULL,
  83. `password` varchar(100) DEFAULT NULL,
  84. `salt` varchar(20) DEFAULT NULL,
  85. `created` datetime DEFAULT NULL,
  86. PRIMARY KEY (`id`),
  87. UNIQUE KEY `mqtt_username` (`username`)
  88. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  89. MQTT ACL Table
  90. --------------
  91. .. code-block:: sql
  92. CREATE TABLE `mqtt_acl` (
  93. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  94. `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow',
  95. `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
  96. `username` varchar(100) DEFAULT NULL COMMENT 'Username',
  97. `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
  98. `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
  99. `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
  100. PRIMARY KEY (`id`)
  101. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  102. Configure emqttd_plugin_mysql/etc/plugin.config
  103. -----------------------------------------------
  104. Configure MySQL host, username, password and database:
  105. .. code-block:: erlang
  106. [
  107. {emqttd_plugin_mysql, [
  108. {mysql_pool, [
  109. %% ecpool options
  110. {pool_size, 4},
  111. {auto_reconnect, 3},
  112. %% mysql options
  113. {host, "localhost"},
  114. {port, 3306},
  115. {user, ""},
  116. {password, ""},
  117. {database, "mqtt"},
  118. {encoding, utf8}
  119. ]},
  120. %% select password only
  121. {authquery, "select password from mqtt_user where username = '%u' limit 1"},
  122. %% hash algorithm: md5, sha, sha256, pbkdf2?
  123. {password_hash, sha256},
  124. %% select password with salt
  125. %% {authquery, "select password, salt from mqtt_user where username = '%u'"},
  126. %% sha256 with salt prefix
  127. %% {password_hash, {salt, sha256}},
  128. %% sha256 with salt suffix
  129. %% {password_hash, {sha256, salt}},
  130. %% comment this query, the acl will be disabled
  131. {aclquery, "select * from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"},
  132. %% If no rules matched, return...
  133. {acl_nomatch, allow}
  134. ]}
  135. ].
  136. Load emqttd_plugin_mysql plugin
  137. -------------------------------
  138. .. code-block:: bash
  139. ./bin/emqttd_ctl plugins load emqttd_plugin_mysql
  140. ------------------------------------------------
  141. emqttd_plugin_pgsql - PostgreSQL Auth/ACL Plugin
  142. ------------------------------------------------
  143. MQTT Authentication, ACL with PostgreSQL Database.
  144. MQTT User Table
  145. ---------------
  146. .. code-block:: sql
  147. CREATE TABLE mqtt_user (
  148. id SERIAL primary key,
  149. username character varying(100),
  150. password character varying(100),
  151. salt character varying(40)
  152. );
  153. MQTT ACL Table
  154. --------------
  155. .. code-block:: sql
  156. CREATE TABLE mqtt_acl (
  157. id SERIAL primary key,
  158. allow integer,
  159. ipaddr character varying(60),
  160. username character varying(100),
  161. clientid character varying(100),
  162. access integer,
  163. topic character varying(100)
  164. );
  165. INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic)
  166. VALUES
  167. (1,1,NULL,'$all',NULL,2,'#'),
  168. (2,0,NULL,'$all',NULL,1,'$SYS/#'),
  169. (3,0,NULL,'$all',NULL,1,'eq #'),
  170. (5,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
  171. (6,1,'127.0.0.1',NULL,NULL,2,'#'),
  172. (7,1,NULL,'dashboard',NULL,1,'$SYS/#');
  173. Configure emqttd_plugin_pgsql/etc/plugin.config
  174. -----------------------------------------------
  175. Configure host, username, password and database of PostgreSQL:
  176. .. code-block:: erlang
  177. [
  178. {emqttd_plugin_pgsql, [
  179. {pgsql_pool, [
  180. %% ecpool options
  181. {pool_size, 4},
  182. {auto_reconnect, 3},
  183. %% pgsql options
  184. {host, "localhost"},
  185. {port, 5432},
  186. {username, "feng"},
  187. {password, ""},
  188. {database, "mqtt"},
  189. {encoding, utf8}
  190. ]},
  191. %% select password only
  192. {authquery, "select password from mqtt_user where username = '%u' limit 1"},
  193. %% hash algorithm: md5, sha, sha256, pbkdf2?
  194. {password_hash, sha256},
  195. %% select password with salt
  196. %% {authquery, "select password, salt from mqtt_user where username = '%u'"},
  197. %% sha256 with salt prefix
  198. %% {password_hash, {salt, sha256}},
  199. %% sha256 with salt suffix
  200. %% {password_hash, {sha256, salt}},
  201. %% Comment this query, the acl will be disabled. Notice: don't edit this query!
  202. {aclquery, "select allow, ipaddr, username, clientid, access, topic from mqtt_acl
  203. where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"},
  204. %% If no rules matched, return...
  205. {acl_nomatch, allow}
  206. ]}
  207. ].
  208. Load emqttd_plugin_pgsql Plugin
  209. -------------------------------
  210. .. code-block:: bash
  211. ./bin/emqttd_ctl plugins load emqttd_plugin_pgsql
  212. -------------------------------------------
  213. emqttd_plugin_redis - Redis Auth/ACL Plugin
  214. -------------------------------------------
  215. MQTT Authentication, ACL with Redis.
  216. Configure emqttd_plugin_redis/etc/plugin.config
  217. -----------------------------------------------
  218. .. code-block:: erlang
  219. [
  220. {emqttd_plugin_redis, [
  221. {eredis_pool, [
  222. %% ecpool options
  223. {pool_size, 8},
  224. {auto_reconnect, 2},
  225. %% eredis options
  226. {host, "127.0.0.1"},
  227. {port, 6379},
  228. {database, 0},
  229. {password, ""}
  230. ]},
  231. %% HMGET mqtt_user:%u password
  232. {authcmd, ["HGET", "mqtt_user:%u", "password"]},
  233. %% Password hash algorithm: plain, md5, sha, sha256, pbkdf2?
  234. {password_hash, sha256},
  235. %% SMEMBERS mqtt_acl:%u
  236. {aclcmd, ["SMEMBERS", "mqtt_acl:%u"]},
  237. %% If no rules matched, return...
  238. {acl_nomatch, deny},
  239. %% Store subscriptions to redis when SUBSCRIBE packets received.
  240. {subcmd, ["HMSET", "mqtt_subs:%u"]},
  241. %% Load Subscriptions form Redis when client connected.
  242. {loadsub, ["HGETALL", "mqtt_subs:%u"]},
  243. %% Remove subscriptions from redis when UNSUBSCRIBE packets received.
  244. {unsubcmd, ["HDEL", "mqtt_subs:%u"]}
  245. ]}
  246. ].
  247. Load emqttd_plugin_redis Plugin
  248. -------------------------------
  249. .. code-block:: bash
  250. ./bin/emqttd_ctl plugins load emqttd_plugin_redis
  251. -----------------------------
  252. emqttd_stomp - STOMP Protocol
  253. -----------------------------
  254. Support STOMP 1.0/1.1/1.2 clients to connect to emqttd broker and communicate with MQTT Clients.
  255. Configure emqttd_stomp/etc/plugin.config
  256. ----------------------------------------
  257. .. NOTE:: Default Port for STOMP Protocol: 61613
  258. .. code-block:: erlang
  259. [
  260. {emqttd_stomp, [
  261. {default_user, [
  262. {login, "guest"},
  263. {passcode, "guest"}
  264. ]},
  265. {allow_anonymous, true},
  266. %%TODO: unused...
  267. {frame, [
  268. {max_headers, 10},
  269. {max_header_length, 1024},
  270. {max_body_length, 8192}
  271. ]},
  272. {listeners, [
  273. {emqttd_stomp, 61613, [
  274. {acceptors, 4},
  275. {max_clients, 512}
  276. ]}
  277. ]}
  278. ]}
  279. ].
  280. Load emqttd_stomp Plugin
  281. ------------------------
  282. .. code-block:: bash
  283. ./bin/emqttd_ctl plugins load emqttd_stomp
  284. -----------------------------------
  285. emqttd_sockjs - STOMP/SockJS Plugin
  286. -----------------------------------
  287. emqttd_sockjs plugin enables web browser to connect to emqttd broker and communicate with MQTT clients.
  288. .. NOTE:: Default TCP Port: 61616
  289. Configure emqttd_sockjs
  290. -----------------------
  291. .. code-block:: erlang
  292. [
  293. {emqttd_sockjs, [
  294. {sockjs, []},
  295. {cowboy_listener, {stomp_sockjs, 61616, 4}},
  296. ]}
  297. ].
  298. Load emqttd_sockjs Plugin
  299. -------------------------
  300. .. NOTE:: emqttd_stomp Plugin required.
  301. .. code-block:: bash
  302. ./bin/emqttd_ctl plugins load emqttd_stomp
  303. ./bin/emqttd_ctl plugins load emqttd_sockjs
  304. SockJS Demo Page
  305. ----------------
  306. http://localhost:61616/index.html
  307. ---------------------------
  308. emqttd_recon - Recon Plugin
  309. ---------------------------
  310. The plugin loads `recon`_ library on a running emqttd broker. Recon libray helps debug and optimize an Erlang application.
  311. Load emqttd_recon Plugin
  312. ------------------------
  313. .. code-block:: bash
  314. ./bin/emqttd_ctl plugins load emqttd_recon
  315. Recon CLI
  316. ---------
  317. .. code-block:: bash
  318. ./bin/emqttd_ctl recon
  319. recon memory #recon_alloc:memory/2
  320. recon allocated #recon_alloc:memory(allocated_types, current|max)
  321. recon bin_leak #recon:bin_leak(100)
  322. recon node_stats #recon:node_stats(10, 1000)
  323. recon remote_load Mod #recon:remote_load(Mod)
  324. ------------------------
  325. Plugin Development Guide
  326. ------------------------
  327. Create a Plugin Project
  328. -----------------------
  329. Clone emqttd source from github.com::
  330. git clone https://github.com/emqtt/emqttd.git
  331. Create a plugin project under 'plugins' folder::
  332. cd plugins && mkdir emqttd_my_plugin
  333. cd emqttd_my_plugin && rebar create-app appid=emqttd_my_plugin
  334. Template Plugin: https://github.com/emqtt/emqttd_plugin_template
  335. Register Auth/ACL Modules
  336. -------------------------
  337. emqttd_auth_demo.erl - demo authentication module:
  338. .. code-block:: erlang
  339. -module(emqttd_auth_demo).
  340. -behaviour(emqttd_auth_mod).
  341. -include("../../../include/emqttd.hrl").
  342. -export([init/1, check/3, description/0]).
  343. init(Opts) -> {ok, Opts}.
  344. check(#mqtt_client{client_id = ClientId, username = Username}, Password, _Opts) ->
  345. io:format("Auth Demo: clientId=~p, username=~p, password=~p~n",
  346. [ClientId, Username, Password]),
  347. ok.
  348. description() -> "Demo Auth Module".
  349. emqttd_acl_demo.erl - demo ACL module:
  350. .. code-block:: erlang
  351. -module(emqttd_acl_demo).
  352. -include("../../../include/emqttd.hrl").
  353. %% ACL callbacks
  354. -export([init/1, check_acl/2, reload_acl/1, description/0]).
  355. init(Opts) ->
  356. {ok, Opts}.
  357. check_acl({Client, PubSub, Topic}, Opts) ->
  358. io:format("ACL Demo: ~p ~p ~p~n", [Client, PubSub, Topic]),
  359. allow.
  360. reload_acl(_Opts) ->
  361. ok.
  362. description() -> "ACL Module Demo".
  363. emqttd_plugin_template_app.erl - Register the auth/ACL modules:
  364. .. code-block:: erlang
  365. ok = emqttd_access_control:register_mod(auth, emqttd_auth_demo, []),
  366. ok = emqttd_access_control:register_mod(acl, emqttd_acl_demo, []),
  367. Register Callbacks for Hooks
  368. -----------------------------
  369. The plugin could register callbacks for hooks. The hooks will be run by the broker when a client connected/disconnected, a topic subscribed/unsubscribed or a message published/delivered:
  370. +------------------------+---------------------------------------+
  371. | Name | Description |
  372. +------------------------+---------------------------------------+
  373. | client.connected | Run when a client connected to the |
  374. | | broker successfully |
  375. +------------------------+---------------------------------------+
  376. | client.subscribe | Run before a client subscribes topics |
  377. +------------------------+---------------------------------------+
  378. | client.subscribe.after | Run after a client subscribed topics |
  379. +------------------------+---------------------------------------+
  380. | client.unsubscribe | Run when a client unsubscribes topics |
  381. +------------------------+---------------------------------------+
  382. | message.publish | Run when a message is published |
  383. +------------------------+---------------------------------------+
  384. | message.delivered | Run when a message is delivered |
  385. +------------------------+---------------------------------------+
  386. | message.acked | Run when a message(qos1/2) is acked |
  387. +------------------------+---------------------------------------+
  388. | client.disconnected | Run when a client is disconnnected |
  389. +------------------------+---------------------------------------+
  390. emqttd_plugin_template.erl for example:
  391. .. code-block:: erlang
  392. %% Called when the plugin application start
  393. load(Env) ->
  394. emqttd:hook('client.connected', fun ?MODULE:on_client_connected/3, [Env]),
  395. emqttd:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Env]),
  396. emqttd:hook('client.subscribe', fun ?MODULE:on_client_subscribe/3, [Env]),
  397. emqttd:hook('client.subscribe.after', fun ?MODULE:on_client_subscribe_after/3, [Env]),
  398. emqttd:hook('client.unsubscribe', fun ?MODULE:on_client_unsubscribe/3, [Env]),
  399. emqttd:hook('message.publish', fun ?MODULE:on_message_publish/2, [Env]),
  400. emqttd:hook('message.delivered', fun ?MODULE:on_message_delivered/3, [Env]),
  401. emqttd:hook('message.acked', fun ?MODULE:on_message_acked/3, [Env]).
  402. Register CLI Modules
  403. --------------------
  404. emqttd_cli_demo.erl:
  405. .. code-block:: erlang
  406. -module(emqttd_cli_demo).
  407. -include("../../../include/emqttd_cli.hrl").
  408. -export([cmd/1]).
  409. cmd(["arg1", "arg2"]) ->
  410. ?PRINT_MSG("ok");
  411. cmd(_) ->
  412. ?USAGE([{"cmd arg1 arg2", "cmd demo"}]).
  413. emqttd_plugin_template_app.erl - register the CLI module to emqttd broker:
  414. .. code-block:: erlang
  415. emqttd_ctl:register_cmd(cmd, {emqttd_cli_demo, cmd}, []).
  416. There will be a new CLI after the plugin loaded::
  417. ./bin/emqttd_ctl cmd arg1 arg2
  418. .. _emqttd_dashboard: https://github.com/emqtt/emqttd_dashboard
  419. .. _emqttd_plugin_mysql: https://github.com/emqtt/emqttd_plugin_mysql
  420. .. _emqttd_plugin_pgsql: https://github.com/emqtt/emqttd_plugin_pgsql
  421. .. _emqttd_plugin_redis: https://github.com/emqtt/emqttd_plugin_redis
  422. .. _emqttd_stomp: https://github.com/emqtt/emqttd_stomp
  423. .. _emqttd_sockjs: https://github.com/emqtt/emqttd_sockjs
  424. .. _emqttd_recon: https://github.com/emqtt/emqttd_recon
  425. .. _emqttd_plugin_template: https://github.com/emqtt/emqttd_plugin_template
  426. .. _recon: http://ferd.github.io/recon/