emqx_mqtt.hrl 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2017-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -ifndef(EMQ_X_MQTT_HRL).
  17. -define(EMQ_X_MQTT_HRL, true).
  18. -define(UINT_MAX, 16#FFFFFFFF).
  19. %%--------------------------------------------------------------------
  20. %% MQTT SockOpts
  21. %%--------------------------------------------------------------------
  22. -define(MQTT_SOCKOPTS, [binary, {packet, raw}, {reuseaddr, true},
  23. {backlog, 512}, {nodelay, true}]).
  24. %%--------------------------------------------------------------------
  25. %% MQTT Protocol Version and Names
  26. %%--------------------------------------------------------------------
  27. -define(MQTT_SN_PROTO_V1, 1).
  28. -define(MQTT_PROTO_V3, 3).
  29. -define(MQTT_PROTO_V4, 4).
  30. -define(MQTT_PROTO_V5, 5).
  31. -define(PROTOCOL_NAMES, [
  32. {?MQTT_SN_PROTO_V1, <<"MQTT-SN">>}, %% XXX:Compatible with emqx-sn plug-in
  33. {?MQTT_PROTO_V3, <<"MQIsdp">>},
  34. {?MQTT_PROTO_V4, <<"MQTT">>},
  35. {?MQTT_PROTO_V5, <<"MQTT">>}]).
  36. %%--------------------------------------------------------------------
  37. %% MQTT QoS Levels
  38. %%--------------------------------------------------------------------
  39. -define(QOS_0, 0). %% At most once
  40. -define(QOS_1, 1). %% At least once
  41. -define(QOS_2, 2). %% Exactly once
  42. -define(IS_QOS(I), (I >= ?QOS_0 andalso I =< ?QOS_2)).
  43. -define(QOS_I(Name),
  44. begin
  45. (case Name of
  46. ?QOS_0 -> ?QOS_0;
  47. qos0 -> ?QOS_0;
  48. at_most_once -> ?QOS_0;
  49. ?QOS_1 -> ?QOS_1;
  50. qos1 -> ?QOS_1;
  51. at_least_once -> ?QOS_1;
  52. ?QOS_2 -> ?QOS_2;
  53. qos2 -> ?QOS_2;
  54. exactly_once -> ?QOS_2
  55. end)
  56. end).
  57. -define(IS_QOS_NAME(I),
  58. (I =:= qos0 orelse I =:= at_most_once orelse
  59. I =:= qos1 orelse I =:= at_least_once orelse
  60. I =:= qos2 orelse I =:= exactly_once)).
  61. %%--------------------------------------------------------------------
  62. %% Maximum ClientId Length.
  63. %%--------------------------------------------------------------------
  64. -define(MAX_CLIENTID_LEN, 65535).
  65. %%--------------------------------------------------------------------
  66. %% MQTT Control Packet Types
  67. %%--------------------------------------------------------------------
  68. -define(RESERVED, 0). %% Reserved
  69. -define(CONNECT, 1). %% Client request to connect to Server
  70. -define(CONNACK, 2). %% Server to Client: Connect acknowledgment
  71. -define(PUBLISH, 3). %% Publish message
  72. -define(PUBACK, 4). %% Publish acknowledgment
  73. -define(PUBREC, 5). %% Publish received (assured delivery part 1)
  74. -define(PUBREL, 6). %% Publish release (assured delivery part 2)
  75. -define(PUBCOMP, 7). %% Publish complete (assured delivery part 3)
  76. -define(SUBSCRIBE, 8). %% Client subscribe request
  77. -define(SUBACK, 9). %% Server Subscribe acknowledgment
  78. -define(UNSUBSCRIBE, 10). %% Unsubscribe request
  79. -define(UNSUBACK, 11). %% Unsubscribe acknowledgment
  80. -define(PINGREQ, 12). %% PING request
  81. -define(PINGRESP, 13). %% PING response
  82. -define(DISCONNECT, 14). %% Client or Server is disconnecting
  83. -define(AUTH, 15). %% Authentication exchange
  84. %%--------------------------------------------------------------------
  85. %% MQTT V3.1.1 Connect Return Codes
  86. %%--------------------------------------------------------------------
  87. -define(CONNACK_ACCEPT, 0). %% Connection accepted
  88. -define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version
  89. -define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server
  90. -define(CONNACK_SERVER, 3). %% Server unavailable
  91. -define(CONNACK_CREDENTIALS, 4). %% Username or password is malformed
  92. -define(CONNACK_AUTH, 5). %% Client is not authorized to connect
  93. %%--------------------------------------------------------------------
  94. %% MQTT V5.0 Reason Codes
  95. %%--------------------------------------------------------------------
  96. -define(RC_SUCCESS, 16#00).
  97. -define(RC_NORMAL_DISCONNECTION, 16#00).
  98. -define(RC_GRANTED_QOS_0, 16#00).
  99. -define(RC_GRANTED_QOS_1, 16#01).
  100. -define(RC_GRANTED_QOS_2, 16#02).
  101. -define(RC_DISCONNECT_WITH_WILL_MESSAGE, 16#04).
  102. -define(RC_NO_MATCHING_SUBSCRIBERS, 16#10).
  103. -define(RC_NO_SUBSCRIPTION_EXISTED, 16#11).
  104. -define(RC_CONTINUE_AUTHENTICATION, 16#18).
  105. -define(RC_RE_AUTHENTICATE, 16#19).
  106. -define(RC_UNSPECIFIED_ERROR, 16#80).
  107. -define(RC_MALFORMED_PACKET, 16#81).
  108. -define(RC_PROTOCOL_ERROR, 16#82).
  109. -define(RC_IMPLEMENTATION_SPECIFIC_ERROR, 16#83).
  110. -define(RC_UNSUPPORTED_PROTOCOL_VERSION, 16#84).
  111. -define(RC_CLIENT_IDENTIFIER_NOT_VALID, 16#85).
  112. -define(RC_BAD_USER_NAME_OR_PASSWORD, 16#86).
  113. -define(RC_NOT_AUTHORIZED, 16#87).
  114. -define(RC_SERVER_UNAVAILABLE, 16#88).
  115. -define(RC_SERVER_BUSY, 16#89).
  116. -define(RC_BANNED, 16#8A).
  117. -define(RC_SERVER_SHUTTING_DOWN, 16#8B).
  118. -define(RC_BAD_AUTHENTICATION_METHOD, 16#8C).
  119. -define(RC_KEEP_ALIVE_TIMEOUT, 16#8D).
  120. -define(RC_SESSION_TAKEN_OVER, 16#8E).
  121. -define(RC_TOPIC_FILTER_INVALID, 16#8F).
  122. -define(RC_TOPIC_NAME_INVALID, 16#90).
  123. -define(RC_PACKET_IDENTIFIER_IN_USE, 16#91).
  124. -define(RC_PACKET_IDENTIFIER_NOT_FOUND, 16#92).
  125. -define(RC_RECEIVE_MAXIMUM_EXCEEDED, 16#93).
  126. -define(RC_TOPIC_ALIAS_INVALID, 16#94).
  127. -define(RC_PACKET_TOO_LARGE, 16#95).
  128. -define(RC_MESSAGE_RATE_TOO_HIGH, 16#96).
  129. -define(RC_QUOTA_EXCEEDED, 16#97).
  130. -define(RC_ADMINISTRATIVE_ACTION, 16#98).
  131. -define(RC_PAYLOAD_FORMAT_INVALID, 16#99).
  132. -define(RC_RETAIN_NOT_SUPPORTED, 16#9A).
  133. -define(RC_QOS_NOT_SUPPORTED, 16#9B).
  134. -define(RC_USE_ANOTHER_SERVER, 16#9C).
  135. -define(RC_SERVER_MOVED, 16#9D).
  136. -define(RC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED, 16#9E).
  137. -define(RC_CONNECTION_RATE_EXCEEDED, 16#9F).
  138. -define(RC_MAXIMUM_CONNECT_TIME, 16#A0).
  139. -define(RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED, 16#A1).
  140. -define(RC_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED, 16#A2).
  141. %%--------------------------------------------------------------------
  142. %% Maximum MQTT Packet ID and Length
  143. %%--------------------------------------------------------------------
  144. -define(MAX_PACKET_ID, 16#FFFF).
  145. -define(MAX_PACKET_SIZE, 16#FFFFFFF).
  146. -define(MAX_TOPIC_AlIAS, 16#FFFF).
  147. -define(RECEIVE_MAXIMUM_LIMIT, ?MAX_PACKET_ID).
  148. %%--------------------------------------------------------------------
  149. %% MQTT Frame Mask
  150. %%--------------------------------------------------------------------
  151. -define(HIGHBIT, 2#10000000).
  152. -define(LOWBITS, 2#01111111).
  153. %%--------------------------------------------------------------------
  154. %% MQTT Packet Fixed Header
  155. %%--------------------------------------------------------------------
  156. -record(mqtt_packet_header, {
  157. type = ?RESERVED,
  158. dup = false,
  159. qos = ?QOS_0,
  160. retain = false
  161. }).
  162. %%--------------------------------------------------------------------
  163. %% MQTT Packets
  164. %%--------------------------------------------------------------------
  165. -define(DEFAULT_SUBOPTS, #{rh => 0, %% Retain Handling
  166. rap => 0, %% Retain as Publish
  167. nl => 0, %% No Local
  168. qos => 0 %% QoS
  169. }).
  170. -record(mqtt_packet_connect, {
  171. proto_name = <<"MQTT">>,
  172. proto_ver = ?MQTT_PROTO_V4,
  173. is_bridge = false,
  174. clean_start = true,
  175. will_flag = false,
  176. will_qos = ?QOS_0,
  177. will_retain = false,
  178. keepalive = 0,
  179. properties = #{},
  180. clientid = <<>>,
  181. will_props = #{},
  182. will_topic = undefined,
  183. will_payload = undefined,
  184. username = undefined,
  185. password = undefined
  186. }).
  187. -record(mqtt_packet_connack, {
  188. ack_flags,
  189. reason_code,
  190. properties = #{}
  191. }).
  192. -record(mqtt_packet_publish, {
  193. topic_name,
  194. packet_id,
  195. properties = #{}
  196. }).
  197. -record(mqtt_packet_puback, {
  198. packet_id,
  199. reason_code,
  200. properties = #{}
  201. }).
  202. -record(mqtt_packet_subscribe, {
  203. packet_id,
  204. properties = #{},
  205. topic_filters
  206. }).
  207. -record(mqtt_packet_suback, {
  208. packet_id,
  209. properties = #{},
  210. reason_codes
  211. }).
  212. -record(mqtt_packet_unsubscribe, {
  213. packet_id,
  214. properties = #{},
  215. topic_filters
  216. }).
  217. -record(mqtt_packet_unsuback, {
  218. packet_id,
  219. properties = #{},
  220. reason_codes
  221. }).
  222. -record(mqtt_packet_disconnect, {
  223. reason_code,
  224. properties = #{}
  225. }).
  226. -record(mqtt_packet_auth, {
  227. reason_code,
  228. properties = #{}
  229. }).
  230. %%--------------------------------------------------------------------
  231. %% MQTT Control Packet
  232. %%--------------------------------------------------------------------
  233. -record(mqtt_packet, {
  234. header :: #mqtt_packet_header{},
  235. variable :: #mqtt_packet_connect{}
  236. | #mqtt_packet_connack{}
  237. | #mqtt_packet_publish{}
  238. | #mqtt_packet_puback{}
  239. | #mqtt_packet_subscribe{}
  240. | #mqtt_packet_suback{}
  241. | #mqtt_packet_unsubscribe{}
  242. | #mqtt_packet_unsuback{}
  243. | #mqtt_packet_disconnect{}
  244. | #mqtt_packet_auth{}
  245. | pos_integer()
  246. | undefined,
  247. payload :: binary() | undefined
  248. }).
  249. %%--------------------------------------------------------------------
  250. %% MQTT Message Internal
  251. %%--------------------------------------------------------------------
  252. -record(mqtt_msg, {
  253. qos = ?QOS_0,
  254. retain = false,
  255. dup = false,
  256. packet_id,
  257. topic,
  258. props,
  259. payload
  260. }).
  261. %%--------------------------------------------------------------------
  262. %% MQTT Packet Match
  263. %%--------------------------------------------------------------------
  264. -define(CONNECT_PACKET(),
  265. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}}).
  266. -define(CONNECT_PACKET(Var),
  267. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT},
  268. variable = Var}).
  269. -define(CONNACK_PACKET(ReasonCode),
  270. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  271. variable = #mqtt_packet_connack{ack_flags = 0,
  272. reason_code = ReasonCode}
  273. }).
  274. -define(CONNACK_PACKET(ReasonCode, SessPresent),
  275. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  276. variable = #mqtt_packet_connack{ack_flags = SessPresent,
  277. reason_code = ReasonCode}
  278. }).
  279. -define(CONNACK_PACKET(ReasonCode, SessPresent, Properties),
  280. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  281. variable = #mqtt_packet_connack{ack_flags = SessPresent,
  282. reason_code = ReasonCode,
  283. properties = Properties}
  284. }).
  285. -define(AUTH_PACKET(),
  286. #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH},
  287. variable = #mqtt_packet_auth{reason_code = 0}
  288. }).
  289. -define(AUTH_PACKET(ReasonCode),
  290. #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH},
  291. variable = #mqtt_packet_auth{reason_code = ReasonCode}
  292. }).
  293. -define(AUTH_PACKET(ReasonCode, Properties),
  294. #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH},
  295. variable = #mqtt_packet_auth{reason_code = ReasonCode,
  296. properties = Properties}
  297. }).
  298. -define(PUBLISH_PACKET(QoS),
  299. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, qos = QoS}}).
  300. -define(PUBLISH_PACKET(QoS, PacketId),
  301. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  302. qos = QoS},
  303. variable = #mqtt_packet_publish{packet_id = PacketId}
  304. }).
  305. -define(PUBLISH_PACKET(QoS, Topic, PacketId),
  306. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  307. qos = QoS},
  308. variable = #mqtt_packet_publish{topic_name = Topic,
  309. packet_id = PacketId}
  310. }).
  311. -define(PUBLISH_PACKET(QoS, Topic, PacketId, Payload),
  312. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  313. qos = QoS},
  314. variable = #mqtt_packet_publish{topic_name = Topic,
  315. packet_id = PacketId},
  316. payload = Payload
  317. }).
  318. -define(PUBLISH_PACKET(QoS, Topic, PacketId, Properties, Payload),
  319. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  320. qos = QoS},
  321. variable = #mqtt_packet_publish{topic_name = Topic,
  322. packet_id = PacketId,
  323. properties = Properties},
  324. payload = Payload
  325. }).
  326. -define(PUBACK_PACKET(PacketId),
  327. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBACK},
  328. variable = #mqtt_packet_puback{packet_id = PacketId,
  329. reason_code = 0}
  330. }).
  331. -define(PUBACK_PACKET(PacketId, ReasonCode),
  332. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBACK},
  333. variable = #mqtt_packet_puback{packet_id = PacketId,
  334. reason_code = ReasonCode}
  335. }).
  336. -define(PUBACK_PACKET(PacketId, ReasonCode, Properties),
  337. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBACK},
  338. variable = #mqtt_packet_puback{packet_id = PacketId,
  339. reason_code = ReasonCode,
  340. properties = Properties}
  341. }).
  342. -define(PUBREC_PACKET(PacketId),
  343. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREC},
  344. variable = #mqtt_packet_puback{packet_id = PacketId,
  345. reason_code = 0}
  346. }).
  347. -define(PUBREC_PACKET(PacketId, ReasonCode),
  348. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREC},
  349. variable = #mqtt_packet_puback{packet_id = PacketId,
  350. reason_code = ReasonCode}
  351. }).
  352. -define(PUBREC_PACKET(PacketId, ReasonCode, Properties),
  353. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREC},
  354. variable = #mqtt_packet_puback{packet_id = PacketId,
  355. reason_code = ReasonCode,
  356. properties = Properties}
  357. }).
  358. -define(PUBREL_PACKET(PacketId),
  359. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL,
  360. qos = ?QOS_1},
  361. variable = #mqtt_packet_puback{packet_id = PacketId,
  362. reason_code = 0}
  363. }).
  364. -define(PUBREL_PACKET(PacketId, ReasonCode),
  365. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL,
  366. qos = ?QOS_1},
  367. variable = #mqtt_packet_puback{packet_id = PacketId,
  368. reason_code = ReasonCode}
  369. }).
  370. -define(PUBREL_PACKET(PacketId, ReasonCode, Properties),
  371. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL,
  372. qos = ?QOS_1},
  373. variable = #mqtt_packet_puback{packet_id = PacketId,
  374. reason_code = ReasonCode,
  375. properties = Properties}
  376. }).
  377. -define(PUBCOMP_PACKET(PacketId),
  378. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBCOMP},
  379. variable = #mqtt_packet_puback{packet_id = PacketId,
  380. reason_code = 0}
  381. }).
  382. -define(PUBCOMP_PACKET(PacketId, ReasonCode),
  383. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBCOMP},
  384. variable = #mqtt_packet_puback{packet_id = PacketId,
  385. reason_code = ReasonCode}
  386. }).
  387. -define(PUBCOMP_PACKET(PacketId, ReasonCode, Properties),
  388. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBCOMP},
  389. variable = #mqtt_packet_puback{packet_id = PacketId,
  390. reason_code = ReasonCode,
  391. properties = Properties}
  392. }).
  393. -define(SUBSCRIBE_PACKET(PacketId, TopicFilters),
  394. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE,
  395. qos = ?QOS_1},
  396. variable = #mqtt_packet_subscribe{packet_id = PacketId,
  397. topic_filters = TopicFilters}
  398. }).
  399. -define(SUBSCRIBE_PACKET(PacketId, Properties, TopicFilters),
  400. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE,
  401. qos = ?QOS_1},
  402. variable = #mqtt_packet_subscribe{packet_id = PacketId,
  403. properties = Properties,
  404. topic_filters = TopicFilters}
  405. }).
  406. -define(SUBACK_PACKET(PacketId, ReasonCodes),
  407. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK},
  408. variable = #mqtt_packet_suback{packet_id = PacketId,
  409. reason_codes = ReasonCodes}
  410. }).
  411. -define(SUBACK_PACKET(PacketId, Properties, ReasonCodes),
  412. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK},
  413. variable = #mqtt_packet_suback{packet_id = PacketId,
  414. properties = Properties,
  415. reason_codes = ReasonCodes}
  416. }).
  417. -define(UNSUBSCRIBE_PACKET(PacketId, TopicFilters),
  418. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE,
  419. qos = ?QOS_1},
  420. variable = #mqtt_packet_unsubscribe{packet_id = PacketId,
  421. topic_filters = TopicFilters}
  422. }).
  423. -define(UNSUBSCRIBE_PACKET(PacketId, Properties, TopicFilters),
  424. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE,
  425. qos = ?QOS_1},
  426. variable = #mqtt_packet_unsubscribe{packet_id = PacketId,
  427. properties = Properties,
  428. topic_filters = TopicFilters}
  429. }).
  430. -define(UNSUBACK_PACKET(PacketId),
  431. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
  432. variable = #mqtt_packet_unsuback{packet_id = PacketId}
  433. }).
  434. -define(UNSUBACK_PACKET(PacketId, ReasonCodes),
  435. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
  436. variable = #mqtt_packet_unsuback{packet_id = PacketId,
  437. reason_codes = ReasonCodes}
  438. }).
  439. -define(UNSUBACK_PACKET(PacketId, Properties, ReasonCodes),
  440. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
  441. variable = #mqtt_packet_unsuback{packet_id = PacketId,
  442. properties = Properties,
  443. reason_codes = ReasonCodes}
  444. }).
  445. -define(DISCONNECT_PACKET(),
  446. #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT},
  447. variable = #mqtt_packet_disconnect{reason_code = 0}
  448. }).
  449. -define(DISCONNECT_PACKET(ReasonCode),
  450. #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT},
  451. variable = #mqtt_packet_disconnect{reason_code = ReasonCode}
  452. }).
  453. -define(DISCONNECT_PACKET(ReasonCode, Properties),
  454. #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT},
  455. variable = #mqtt_packet_disconnect{reason_code = ReasonCode,
  456. properties = Properties}
  457. }).
  458. -define(PACKET(Type), #mqtt_packet{header = #mqtt_packet_header{type = Type}}).
  459. -define(SHARE, "$share").
  460. -define(SHARE(Group, Topic), emqx_topic:join([<<?SHARE>>, Group, Topic])).
  461. -define(IS_SHARE(Topic), case Topic of <<?SHARE, _/binary>> -> true; _ -> false end).
  462. -define(FRAME_PARSE_ERROR(Reason), {frame_parse_error, Reason}).
  463. -define(FRAME_SERIALIZE_ERROR(Reason), {frame_serialize_error, Reason}).
  464. -define(THROW_FRAME_ERROR(Reason), erlang:throw(?FRAME_PARSE_ERROR(Reason))).
  465. -define(THROW_SERIALIZE_ERROR(Reason), erlang:throw(?FRAME_SERIALIZE_ERROR(Reason))).
  466. -endif.