Skip to content
This repository was archived by the owner on Nov 16, 2020. It is now read-only.

Commit 7c27e7a

Browse files
committed
Add a small test suite
Fix an issue where connection would fail if sec-websocket-protocol header wasn't set (which is perfectly normal).
1 parent d7ec2a4 commit 7c27e7a

File tree

9 files changed

+973
-3
lines changed

9 files changed

+973
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
.erlang.mk/
2+
cover/
23
ebin/
34
plugins/
5+
test/*.beam
46
rabbitmq_web_mqtt.d
57
*.swp

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ include erlang.mk
2222
# Testing.
2323
# --------------------------------------------------------------------
2424

25-
WITH_BROKER_TEST_COMMANDS := rabbit_ws_test_all:all_tests()
25+
WITH_BROKER_TEST_COMMANDS := rabbit_web_mqtt_test_all:all_tests()

src/rabbit_web_mqtt_handler.erl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ websocket_init(_, Req, Opts) ->
4545
ProcessorState = rabbit_mqtt_processor:initial_state(Sock,
4646
rabbit_mqtt_reader:ssl_login_name(Sock),
4747
fun send_reply/2),
48-
{SecWsProtocol, Req1} = cowboy_req:header(<<"sec-websocket-protocol">>, Req),
49-
Req2 = cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, SecWsProtocol, Req1),
48+
Req2 = case cowboy_req:header(<<"sec-websocket-protocol">>, Req) of
49+
{undefined, Req1} ->
50+
Req1;
51+
{SecWsProtocol, Req1} ->
52+
cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, SecWsProtocol, Req1)
53+
end,
5054
Req3 = cowboy_req:compact(Req2),
5155
{ok, Req3, #state{
5256
conn_name = ConnStr,

test/src/emqttc_packet.hrl

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
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+
%%% emqttc packet header.
24+
%%% @end
25+
%%%-----------------------------------------------------------------------------
26+
27+
%%------------------------------------------------------------------------------
28+
%% MQTT Protocol Version and Levels
29+
%%------------------------------------------------------------------------------
30+
-define(MQTT_PROTO_V31, 3).
31+
-define(MQTT_PROTO_V311, 4).
32+
33+
-define(PROTOCOL_NAMES, [
34+
{?MQTT_PROTO_V31, <<"MQIsdp">>},
35+
{?MQTT_PROTO_V311, <<"MQTT">>}]).
36+
37+
-type mqtt_vsn() :: ?MQTT_PROTO_V31 | ?MQTT_PROTO_V311.
38+
39+
%%------------------------------------------------------------------------------
40+
%% QoS Levels
41+
%%------------------------------------------------------------------------------
42+
43+
-define(QOS_0, 0).
44+
-define(QOS_1, 1).
45+
-define(QOS_2, 2).
46+
47+
-define(IS_QOS(I), (I >= ?QOS_0 andalso I =< ?QOS_2)).
48+
49+
-type mqtt_qos() :: ?QOS_0 | ?QOS_1 | ?QOS_2.
50+
51+
%%------------------------------------------------------------------------------
52+
%% Default Keepalive Timeout(secs)
53+
%%------------------------------------------------------------------------------
54+
-define(KEEPALIVE, 90).
55+
56+
%%------------------------------------------------------------------------------
57+
%% Max ClientId Length. Why 1024? NiDongDe!
58+
%%------------------------------------------------------------------------------
59+
-define(MAX_CLIENTID_LEN, 1024).
60+
61+
%%------------------------------------------------------------------------------
62+
%% MQTT Control Packet Types
63+
%%------------------------------------------------------------------------------
64+
-define(RESERVED, 0). %% Reserved
65+
-define(CONNECT, 1). %% Client request to connect to Server
66+
-define(CONNACK, 2). %% Server to Client: Connect acknowledgment
67+
-define(PUBLISH, 3). %% Publish message
68+
-define(PUBACK, 4). %% Publish acknowledgment
69+
-define(PUBREC, 5). %% Publish received (assured delivery part 1)
70+
-define(PUBREL, 6). %% Publish release (assured delivery part 2)
71+
-define(PUBCOMP, 7). %% Publish complete (assured delivery part 3)
72+
-define(SUBSCRIBE, 8). %% Client subscribe request
73+
-define(SUBACK, 9). %% Server Subscribe acknowledgment
74+
-define(UNSUBSCRIBE, 10). %% Unsubscribe request
75+
-define(UNSUBACK, 11). %% Unsubscribe acknowledgment
76+
-define(PINGREQ, 12). %% PING request
77+
-define(PINGRESP, 13). %% PING response
78+
-define(DISCONNECT, 14). %% Client is disconnecting
79+
80+
-define(TYPE_NAMES, [
81+
'CONNECT',
82+
'CONNACK',
83+
'PUBLISH',
84+
'PUBACK',
85+
'PUBREC',
86+
'PUBREL',
87+
'PUBCOMP',
88+
'SUBSCRIBE',
89+
'SUBACK',
90+
'UNSUBSCRIBE',
91+
'UNSUBACK',
92+
'PINGREQ',
93+
'PINGRESP',
94+
'DISCONNECT']).
95+
96+
-type mqtt_packet_type() :: ?RESERVED..?DISCONNECT.
97+
98+
%%------------------------------------------------------------------------------
99+
%% MQTT Connect Return Codes
100+
%%------------------------------------------------------------------------------
101+
-define(CONNACK_ACCEPT, 0). %% Connection accepted
102+
-define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version
103+
-define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server
104+
-define(CONNACK_SERVER, 3). %% Server unavailable
105+
-define(CONNACK_CREDENTIALS, 4). %% Username or password is malformed
106+
-define(CONNACK_AUTH, 5). %% Client is not authorized to connect
107+
108+
-type mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH.
109+
110+
%%------------------------------------------------------------------------------
111+
%% MQTT Parser and Serialiser
112+
%%------------------------------------------------------------------------------
113+
-define(MAX_LEN, 16#fffffff).
114+
-define(HIGHBIT, 2#10000000).
115+
-define(LOWBITS, 2#01111111).
116+
117+
%%------------------------------------------------------------------------------
118+
%% MQTT Packet Fixed Header
119+
%%------------------------------------------------------------------------------
120+
-record(mqtt_packet_header, {
121+
type = ?RESERVED :: mqtt_packet_type(),
122+
dup = false :: boolean(),
123+
qos = ?QOS_0 :: mqtt_qos(),
124+
retain = false :: boolean()}).
125+
126+
%%------------------------------------------------------------------------------
127+
%% MQTT Packets
128+
%%------------------------------------------------------------------------------
129+
-type mqtt_packet_id() :: 1..16#ffff | undefined.
130+
131+
-record(mqtt_packet_connect, {
132+
client_id = <<>> :: binary(),
133+
proto_ver = ?MQTT_PROTO_V311 :: mqtt_vsn(),
134+
proto_name = <<"MQTT">> :: binary(),
135+
will_retain = false :: boolean(),
136+
will_qos = ?QOS_0 :: mqtt_qos(),
137+
will_flag = false :: boolean(),
138+
clean_sess = false :: boolean(),
139+
keep_alive = 60 :: non_neg_integer(),
140+
will_topic = undefined :: undefined | binary(),
141+
will_msg = undefined :: undefined | binary(),
142+
username = undefined :: undefined | binary(),
143+
password = undefined :: undefined | binary()}).
144+
145+
-record(mqtt_packet_connack, {
146+
ack_flags = ?RESERVED :: 0 | 1,
147+
return_code :: mqtt_connack() }).
148+
149+
-record(mqtt_packet_publish, {
150+
topic_name :: binary(),
151+
packet_id :: mqtt_packet_id() }).
152+
153+
-record(mqtt_packet_puback, {
154+
packet_id :: mqtt_packet_id() }).
155+
156+
-record(mqtt_packet_subscribe, {
157+
packet_id :: mqtt_packet_id(),
158+
topic_table :: list({binary(), mqtt_qos()}) }).
159+
160+
-record(mqtt_packet_unsubscribe, {
161+
packet_id :: mqtt_packet_id(),
162+
topics :: list(binary()) }).
163+
164+
-record(mqtt_packet_suback, {
165+
packet_id :: mqtt_packet_id(),
166+
qos_table :: list(mqtt_qos() | 128) }).
167+
168+
-record(mqtt_packet_unsuback, {
169+
packet_id :: mqtt_packet_id() }).
170+
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+
%%------------------------------------------------------------------------------
186+
%% MQTT Packet Match
187+
%%------------------------------------------------------------------------------
188+
-define(CONNECT_PACKET(Packet),
189+
#mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}, variable = Packet}).
190+
191+
-define(CONNACK_PACKET(ReturnCode),
192+
#mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK},
193+
variable = #mqtt_packet_connack{return_code = ReturnCode}}).
194+
195+
-define(PUBLISH_PACKET(Qos, Topic, PacketId, Payload),
196+
#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
197+
qos = Qos},
198+
variable = #mqtt_packet_publish{topic_name = Topic,
199+
packet_id = PacketId},
200+
payload = Payload}).
201+
202+
-define(PUBACK_PACKET(Type, PacketId),
203+
#mqtt_packet{header = #mqtt_packet_header{type = Type},
204+
variable = #mqtt_packet_puback{packet_id = PacketId}}).
205+
206+
-define(PUBREL_PACKET(PacketId),
207+
#mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL, qos = ?QOS_1},
208+
variable = #mqtt_packet_puback{packet_id = PacketId}}).
209+
210+
-define(SUBSCRIBE_PACKET(PacketId, TopicTable),
211+
#mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE, qos = ?QOS_1},
212+
variable = #mqtt_packet_subscribe{packet_id = PacketId,
213+
topic_table = TopicTable}}).
214+
-define(SUBACK_PACKET(PacketId, QosTable),
215+
#mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK},
216+
variable = #mqtt_packet_suback{packet_id = PacketId,
217+
qos_table = QosTable}}).
218+
-define(UNSUBSCRIBE_PACKET(PacketId, Topics),
219+
#mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE, qos = ?QOS_1},
220+
variable = #mqtt_packet_unsubscribe{packet_id = PacketId,
221+
topics = Topics}}).
222+
-define(UNSUBACK_PACKET(PacketId),
223+
#mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK},
224+
variable = #mqtt_packet_unsuback{packet_id = PacketId}}).
225+
226+
-define(PACKET(Type),
227+
#mqtt_packet{header = #mqtt_packet_header{type = Type}}).
228+
229+
%%------------------------------------------------------------------------------
230+
%% MQTT Message
231+
%%------------------------------------------------------------------------------
232+
-record(mqtt_message, {
233+
qos = ?QOS_0 :: mqtt_qos(),
234+
retain = false :: boolean(),
235+
dup = false :: boolean(),
236+
msgid :: mqtt_packet_id(),
237+
topic :: binary(),
238+
payload :: binary()}).
239+
240+
-type mqtt_message() :: #mqtt_message{}.

0 commit comments

Comments
 (0)