emqttd_protocol.hrl 11 KB

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