emqttd_protocol.hrl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. %%%-----------------------------------------------------------------------------
  2. %%% @Copyright (C) 2012-2015, Feng Lee <feng@emqtt.io>
  3. %%%
  4. %%% Permission is hereby granted, free of charge, to any person obtaining a copy
  5. %%% of this software and associated documentation files (the "Software"), to deal
  6. %%% in the Software without restriction, including without limitation the rights
  7. %%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. %%% copies of the Software, and to permit persons to whom the Software is
  9. %%% furnished to do so, subject to the following conditions:
  10. %%%
  11. %%% The above copyright notice and this permission notice shall be included in all
  12. %%% copies or substantial portions of the Software.
  13. %%%
  14. %%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. %%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. %%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. %%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. %%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. %%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. %%% SOFTWARE.
  21. %%%-----------------------------------------------------------------------------
  22. %%% @doc
  23. %%% MQTT Protocol Header.
  24. %%%
  25. %%% @end
  26. %%%-----------------------------------------------------------------------------
  27. %%------------------------------------------------------------------------------
  28. %% MQTT Protocol Version and Levels
  29. %%------------------------------------------------------------------------------
  30. -define(MQTT_PROTO_V31, 3).
  31. -define(MQTT_PROTO_V311, 4).
  32. -define(PROTOCOL_NAMES, [
  33. {?MQTT_PROTO_V31, <<"MQIsdp">>},
  34. {?MQTT_PROTO_V311, <<"MQTT">>}]).
  35. -type mqtt_vsn() :: ?MQTT_PROTO_V31 | ?MQTT_PROTO_V311.
  36. %%------------------------------------------------------------------------------
  37. %% MQTT QoS
  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. -type mqtt_qos() :: ?QOS_0 | ?QOS_1 | ?QOS_2.
  44. -type mqtt_qos_name() :: qos0 | at_most_once |
  45. qos1 | at_least_once |
  46. qos2 | exactly_once.
  47. -define(QOS_I(Name),
  48. begin
  49. (case Name of
  50. ?QOS_0 -> ?QOS_0;
  51. qos0 -> ?QOS_0;
  52. at_most_once -> ?QOS_0;
  53. ?QOS_1 -> ?QOS_1;
  54. qos1 -> ?QOS_1;
  55. at_least_once -> ?QOS_1;
  56. ?QOS_2 -> ?QOS_2;
  57. qos2 -> ?QOS_2;
  58. exactly_once -> ?QOS_2
  59. end)
  60. end).
  61. %%------------------------------------------------------------------------------
  62. %% Max ClientId Length. Why 1024? NiDongDe!
  63. %%------------------------------------------------------------------------------
  64. -define(MAX_CLIENTID_LEN, 1024).
  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 is disconnecting
  83. -define(TYPE_NAMES, [
  84. 'CONNECT',
  85. 'CONNACK',
  86. 'PUBLISH',
  87. 'PUBACK',
  88. 'PUBREC',
  89. 'PUBREL',
  90. 'PUBCOMP',
  91. 'SUBSCRIBE',
  92. 'SUBACK',
  93. 'UNSUBSCRIBE',
  94. 'UNSUBACK',
  95. 'PINGREQ',
  96. 'PINGRESP',
  97. 'DISCONNECT']).
  98. -type mqtt_packet_type() :: ?RESERVED..?DISCONNECT.
  99. %%------------------------------------------------------------------------------
  100. %% MQTT Connect Return Codes
  101. %%------------------------------------------------------------------------------
  102. -define(CONNACK_ACCEPT, 0). %% Connection accepted
  103. -define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version
  104. -define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server
  105. -define(CONNACK_SERVER, 3). %% Server unavailable
  106. -define(CONNACK_CREDENTIALS, 4). %% Username or password is malformed
  107. -define(CONNACK_AUTH, 5). %% Client is not authorized to connect
  108. -type mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH.
  109. %%------------------------------------------------------------------------------
  110. %% MQTT Parser and Serialiser
  111. %%------------------------------------------------------------------------------
  112. -define(MAX_LEN, 16#fffffff).
  113. -define(HIGHBIT, 2#10000000).
  114. -define(LOWBITS, 2#01111111).
  115. %%------------------------------------------------------------------------------
  116. %% MQTT Packet Fixed Header
  117. %%------------------------------------------------------------------------------
  118. -record(mqtt_packet_header, {
  119. type = ?RESERVED :: mqtt_packet_type(),
  120. dup = false :: boolean(),
  121. qos = ?QOS_0 :: mqtt_qos(),
  122. retain = false :: boolean()}).
  123. %%------------------------------------------------------------------------------
  124. %% MQTT Packets
  125. %%------------------------------------------------------------------------------
  126. -type mqtt_client_id() :: binary().
  127. -type mqtt_packet_id() :: 1..16#ffff | undefined.
  128. -record(mqtt_packet_connect, {
  129. client_id = <<>> :: mqtt_client_id(),
  130. proto_ver = ?MQTT_PROTO_V311 :: mqtt_vsn(),
  131. proto_name = <<"MQTT">> :: binary(),
  132. will_retain = false :: boolean(),
  133. will_qos = ?QOS_0 :: mqtt_qos(),
  134. will_flag = false :: boolean(),
  135. clean_sess = false :: boolean(),
  136. keep_alive = 60 :: non_neg_integer(),
  137. will_topic = undefined :: undefined | binary(),
  138. will_msg = undefined :: undefined | binary(),
  139. username = undefined :: undefined | binary(),
  140. password = undefined :: undefined | binary()}).
  141. -record(mqtt_packet_connack, {
  142. ack_flags = ?RESERVED :: 0 | 1,
  143. return_code :: mqtt_connack() }).
  144. -record(mqtt_packet_publish, {
  145. topic_name :: binary(),
  146. packet_id :: mqtt_packet_id() }).
  147. -record(mqtt_packet_puback, {
  148. packet_id :: mqtt_packet_id() }).
  149. -record(mqtt_packet_subscribe, {
  150. packet_id :: mqtt_packet_id(),
  151. topic_table :: list({binary(), mqtt_qos()}) }).
  152. -record(mqtt_packet_unsubscribe, {
  153. packet_id :: mqtt_packet_id(),
  154. topics :: list(binary()) }).
  155. -record(mqtt_packet_suback, {
  156. packet_id :: mqtt_packet_id(),
  157. qos_table :: list(mqtt_qos() | 128) }).
  158. -record(mqtt_packet_unsuback, {
  159. packet_id :: mqtt_packet_id() }).
  160. %%------------------------------------------------------------------------------
  161. %% MQTT Control Packet
  162. %%------------------------------------------------------------------------------
  163. -record(mqtt_packet, {
  164. header :: #mqtt_packet_header{},
  165. variable :: #mqtt_packet_connect{} | #mqtt_packet_connack{}
  166. | #mqtt_packet_publish{} | #mqtt_packet_puback{}
  167. | #mqtt_packet_subscribe{} | #mqtt_packet_suback{}
  168. | #mqtt_packet_unsubscribe{} | #mqtt_packet_unsuback{}
  169. | mqtt_packet_id() | undefined,
  170. payload :: binary() | undefined }).
  171. -type mqtt_packet() :: #mqtt_packet{}.
  172. %%------------------------------------------------------------------------------
  173. %% MQTT Packet Match
  174. %%------------------------------------------------------------------------------
  175. -define(CONNECT_PACKET(Var),
  176. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}, variable = Var}).
  177. -define(CONNACK_PACKET(ReturnCode),
  178. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  179. variable = #mqtt_packet_connack{return_code = ReturnCode}}).
  180. -define(PUBLISH_PACKET(Qos, Topic, PacketId, Payload),
  181. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  182. qos = Qos},
  183. variable = #mqtt_packet_publish{topic_name = Topic,
  184. packet_id = PacketId},
  185. payload = Payload}).
  186. -define(PUBLISH(Qos, PacketId),
  187. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  188. qos = Qos},
  189. variable = #mqtt_packet_publish{packet_id = PacketId}}).
  190. -define(PUBACK_PACKET(Type, PacketId),
  191. #mqtt_packet{header = #mqtt_packet_header{type = Type},
  192. variable = #mqtt_packet_puback{packet_id = PacketId}}).
  193. -define(PUBREL_PACKET(PacketId),
  194. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL, qos = ?QOS_1},
  195. variable = #mqtt_packet_puback{packet_id = PacketId}}).
  196. -define(SUBSCRIBE_PACKET(PacketId, TopicTable),
  197. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE, qos = ?QOS_1},
  198. variable = #mqtt_packet_subscribe{packet_id = PacketId,
  199. topic_table = TopicTable}}).
  200. -define(SUBACK_PACKET(PacketId, QosTable),
  201. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK},
  202. variable = #mqtt_packet_suback{packet_id = PacketId,
  203. qos_table = QosTable}}).
  204. -define(UNSUBSCRIBE_PACKET(PacketId, Topics),
  205. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE, qos = ?QOS_1},
  206. variable = #mqtt_packet_unsubscribe{packet_id = PacketId,
  207. topics = Topics}}).
  208. -define(UNSUBACK_PACKET(PacketId),
  209. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
  210. variable = #mqtt_packet_unsuback{packet_id = PacketId}}).
  211. -define(PACKET(Type),
  212. #mqtt_packet{header = #mqtt_packet_header{type = Type}}).