emqttd_protocol.hrl 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
  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. %% MQTT Protocol Header
  17. %%--------------------------------------------------------------------
  18. %% MQTT Protocol Version and Levels
  19. %%--------------------------------------------------------------------
  20. -define(MQTT_PROTO_V31, 3).
  21. -define(MQTT_PROTO_V311, 4).
  22. -define(PROTOCOL_NAMES, [
  23. {?MQTT_PROTO_V31, <<"MQIsdp">>},
  24. {?MQTT_PROTO_V311, <<"MQTT">>}]).
  25. -type mqtt_vsn() :: ?MQTT_PROTO_V31 | ?MQTT_PROTO_V311.
  26. %%--------------------------------------------------------------------
  27. %% MQTT QoS
  28. %%--------------------------------------------------------------------
  29. -define(QOS_0, 0). %% At most once
  30. -define(QOS_1, 1). %% At least once
  31. -define(QOS_2, 2). %% Exactly once
  32. -define(QOS0, 0). %% At most once
  33. -define(QOS1, 1). %% At least once
  34. -define(QOS2, 2). %% Exactly once
  35. -define(IS_QOS(I), (I >= ?QOS0 andalso I =< ?QOS2)).
  36. -type mqtt_qos() :: ?QOS0 | ?QOS1 | ?QOS2.
  37. -type mqtt_qos_name() :: qos0 | at_most_once |
  38. qos1 | at_least_once |
  39. qos2 | exactly_once.
  40. -define(QOS_I(Name),
  41. begin
  42. (case Name of
  43. ?QOS_0 -> ?QOS_0;
  44. qos0 -> ?QOS_0;
  45. at_most_once -> ?QOS_0;
  46. ?QOS_1 -> ?QOS_1;
  47. qos1 -> ?QOS_1;
  48. at_least_once -> ?QOS_1;
  49. ?QOS_2 -> ?QOS_2;
  50. qos2 -> ?QOS_2;
  51. exactly_once -> ?QOS_2
  52. end)
  53. end).
  54. %%--------------------------------------------------------------------
  55. %% Max ClientId Length. Why 1024? NiDongDe...
  56. %%--------------------------------------------------------------------
  57. -define(MAX_CLIENTID_LEN, 1024).
  58. %%--------------------------------------------------------------------
  59. %% MQTT Control Packet Types
  60. %%--------------------------------------------------------------------
  61. -define(RESERVED, 0). %% Reserved
  62. -define(CONNECT, 1). %% Client request to connect to Server
  63. -define(CONNACK, 2). %% Server to Client: Connect acknowledgment
  64. -define(PUBLISH, 3). %% Publish message
  65. -define(PUBACK, 4). %% Publish acknowledgment
  66. -define(PUBREC, 5). %% Publish received (assured delivery part 1)
  67. -define(PUBREL, 6). %% Publish release (assured delivery part 2)
  68. -define(PUBCOMP, 7). %% Publish complete (assured delivery part 3)
  69. -define(SUBSCRIBE, 8). %% Client subscribe request
  70. -define(SUBACK, 9). %% Server Subscribe acknowledgment
  71. -define(UNSUBSCRIBE, 10). %% Unsubscribe request
  72. -define(UNSUBACK, 11). %% Unsubscribe acknowledgment
  73. -define(PINGREQ, 12). %% PING request
  74. -define(PINGRESP, 13). %% PING response
  75. -define(DISCONNECT, 14). %% Client is disconnecting
  76. -define(TYPE_NAMES, [
  77. 'CONNECT',
  78. 'CONNACK',
  79. 'PUBLISH',
  80. 'PUBACK',
  81. 'PUBREC',
  82. 'PUBREL',
  83. 'PUBCOMP',
  84. 'SUBSCRIBE',
  85. 'SUBACK',
  86. 'UNSUBSCRIBE',
  87. 'UNSUBACK',
  88. 'PINGREQ',
  89. 'PINGRESP',
  90. 'DISCONNECT']).
  91. -type mqtt_packet_type() :: ?RESERVED..?DISCONNECT.
  92. %%--------------------------------------------------------------------
  93. %% MQTT Connect Return Codes
  94. %%--------------------------------------------------------------------
  95. -define(CONNACK_ACCEPT, 0). %% Connection accepted
  96. -define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version
  97. -define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server
  98. -define(CONNACK_SERVER, 3). %% Server unavailable
  99. -define(CONNACK_CREDENTIALS, 4). %% Username or password is malformed
  100. -define(CONNACK_AUTH, 5). %% Client is not authorized to connect
  101. -type mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH.
  102. %%--------------------------------------------------------------------
  103. %% MQTT Parser and Serializer
  104. %%--------------------------------------------------------------------
  105. -define(MAX_LEN, 16#fffffff).
  106. -define(HIGHBIT, 2#10000000).
  107. -define(LOWBITS, 2#01111111).
  108. %%--------------------------------------------------------------------
  109. %% MQTT Packet Fixed Header
  110. %%--------------------------------------------------------------------
  111. -record(mqtt_packet_header, {
  112. type = ?RESERVED :: mqtt_packet_type(),
  113. dup = false :: boolean(),
  114. qos = ?QOS_0 :: mqtt_qos(),
  115. retain = false :: boolean()}).
  116. %%--------------------------------------------------------------------
  117. %% MQTT Packets
  118. %%--------------------------------------------------------------------
  119. -type mqtt_client_id() :: binary().
  120. -type mqtt_packet_id() :: 1..16#ffff | undefined.
  121. -record(mqtt_packet_connect, {
  122. client_id = <<>> :: mqtt_client_id(),
  123. proto_ver = ?MQTT_PROTO_V311 :: mqtt_vsn(),
  124. proto_name = <<"MQTT">> :: binary(),
  125. will_retain = false :: boolean(),
  126. will_qos = ?QOS_0 :: mqtt_qos(),
  127. will_flag = false :: boolean(),
  128. clean_sess = false :: boolean(),
  129. keep_alive = 60 :: non_neg_integer(),
  130. will_topic = undefined :: undefined | binary(),
  131. will_msg = undefined :: undefined | binary(),
  132. username = undefined :: undefined | binary(),
  133. password = undefined :: undefined | binary()}).
  134. -record(mqtt_packet_connack, {
  135. ack_flags = ?RESERVED :: 0 | 1,
  136. return_code :: mqtt_connack() }).
  137. -record(mqtt_packet_publish, {
  138. topic_name :: binary(),
  139. packet_id :: mqtt_packet_id() }).
  140. -record(mqtt_packet_puback, {
  141. packet_id :: mqtt_packet_id() }).
  142. -record(mqtt_packet_subscribe, {
  143. packet_id :: mqtt_packet_id(),
  144. topic_table :: list({binary(), mqtt_qos()}) }).
  145. -record(mqtt_packet_unsubscribe, {
  146. packet_id :: mqtt_packet_id(),
  147. topics :: list(binary()) }).
  148. -record(mqtt_packet_suback, {
  149. packet_id :: mqtt_packet_id(),
  150. qos_table :: list(mqtt_qos() | 128) }).
  151. -record(mqtt_packet_unsuback, {
  152. packet_id :: mqtt_packet_id() }).
  153. %%--------------------------------------------------------------------
  154. %% MQTT Control Packet
  155. %%--------------------------------------------------------------------
  156. -record(mqtt_packet, {
  157. header :: #mqtt_packet_header{},
  158. variable :: #mqtt_packet_connect{} | #mqtt_packet_connack{}
  159. | #mqtt_packet_publish{} | #mqtt_packet_puback{}
  160. | #mqtt_packet_subscribe{} | #mqtt_packet_suback{}
  161. | #mqtt_packet_unsubscribe{} | #mqtt_packet_unsuback{}
  162. | mqtt_packet_id() | undefined,
  163. payload :: binary() | undefined }).
  164. -type mqtt_packet() :: #mqtt_packet{}.
  165. %%--------------------------------------------------------------------
  166. %% MQTT Packet Match
  167. %%--------------------------------------------------------------------
  168. -define(CONNECT_PACKET(Var),
  169. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}, variable = Var}).
  170. -define(CONNACK_PACKET(ReturnCode),
  171. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  172. variable = #mqtt_packet_connack{return_code = ReturnCode}}).
  173. -define(CONNACK_PACKET(ReturnCode, SessPresent),
  174. #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
  175. variable = #mqtt_packet_connack{ack_flags = SessPresent,
  176. return_code = ReturnCode}}).
  177. -define(PUBLISH_PACKET(Qos, PacketId),
  178. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  179. qos = Qos},
  180. variable = #mqtt_packet_publish{packet_id = PacketId}}).
  181. -define(PUBLISH_PACKET(Qos, Topic, PacketId, Payload),
  182. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
  183. qos = Qos},
  184. variable = #mqtt_packet_publish{topic_name = Topic,
  185. packet_id = PacketId},
  186. payload = Payload}).
  187. -define(PUBACK_PACKET(Type, PacketId),
  188. #mqtt_packet{header = #mqtt_packet_header{type = Type},
  189. variable = #mqtt_packet_puback{packet_id = PacketId}}).
  190. -define(PUBREL_PACKET(PacketId),
  191. #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL, qos = ?QOS_1},
  192. variable = #mqtt_packet_puback{packet_id = PacketId}}).
  193. -define(SUBSCRIBE_PACKET(PacketId, TopicTable),
  194. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE, qos = ?QOS_1},
  195. variable = #mqtt_packet_subscribe{packet_id = PacketId,
  196. topic_table = TopicTable}}).
  197. -define(SUBACK_PACKET(PacketId, QosTable),
  198. #mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK},
  199. variable = #mqtt_packet_suback{packet_id = PacketId,
  200. qos_table = QosTable}}).
  201. -define(UNSUBSCRIBE_PACKET(PacketId, Topics),
  202. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE, qos = ?QOS_1},
  203. variable = #mqtt_packet_unsubscribe{packet_id = PacketId,
  204. topics = Topics}}).
  205. -define(UNSUBACK_PACKET(PacketId),
  206. #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
  207. variable = #mqtt_packet_unsuback{packet_id = PacketId}}).
  208. -define(PACKET(Type),
  209. #mqtt_packet{header = #mqtt_packet_header{type = Type}}).