diff --git a/docs/conf-sessions.rst b/docs/conf-sessions.rst index b569481cf..71609a1c9 100644 --- a/docs/conf-sessions.rst +++ b/docs/conf-sessions.rst @@ -982,7 +982,7 @@ MQTT It supports publish messages, subscribe and unsubscribe topics, Available request types: -* connect (with options like clean_start, will_topic, username, password, etc.) +* connect (with options like client_id, clean_start, will_topic, username, password, etc.) * disconnect * publish (with topic name, qos level and retain flag) * subscribe (with topic name and qos level) @@ -996,7 +996,7 @@ Example with MQTT as a session type: - + @@ -1023,6 +1023,8 @@ Example with MQTT as a session type: +Note that if a ``client_id`` is omitted upon connecting Tsung will create a random one, prefixed with ``tsung-``. + LDAP ^^^^ diff --git a/include/mqtt.hrl b/include/mqtt.hrl index cb1a3a68e..18e932f85 100644 --- a/include/mqtt.hrl +++ b/include/mqtt.hrl @@ -58,7 +58,7 @@ -record(connect_options, { protocol_name = ?PROTOCOL_NAME, protocol_version = ?PROTOCOL_VERSION, - client_id, + client_id = undefined, clean_start = true, will, keepalive = ?DEFAULT_KEEPALIVE, diff --git a/include/ts_mqtt.hrl b/include/ts_mqtt.hrl index 30006f6b3..a4d7efaed 100644 --- a/include/ts_mqtt.hrl +++ b/include/ts_mqtt.hrl @@ -40,7 +40,8 @@ retained = false, payload, username, - password + password, + client_id }). -record(mqtt_dyndata, { diff --git a/src/test/ts_test_mqtt.erl b/src/test/ts_test_mqtt.erl index 5a503fdff..fa732ca8b 100644 --- a/src/test/ts_test_mqtt.erl +++ b/src/test/ts_test_mqtt.erl @@ -29,6 +29,7 @@ -compile(export_all). -include("ts_profile.hrl"). +-include("ts_mqtt.hrl"). -include("mqtt.hrl"). -include("ts_config.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -51,6 +52,33 @@ encode_connect_test() -> 116,111,112,105,99,0,12,119,105,108,108,95,109,101,115,115, 97,103,101>>, EncodedData). +get_message_with_default_client_id_test() -> + Session = #mqtt_session{}, + State = #state_rcv{session = Session}, + Req = #mqtt_request{type = connect, + will_qos = 0, + will_retain = true, + keepalive = 10}, + {Encoded,_} = ts_mqtt:get_message(Req,State), + {#mqtt{type = Type, arg = Args}, _} = mqtt_frame:decode(Encoded), + #connect_options{client_id = ClientId} = Args, + ?assertEqual(?CONNECT, Type), + ?assertMatch({match,_}, re:run(ClientId, "tsung-")). + +get_message_with_custom_client_id_test() -> + Session = #mqtt_session{}, + State = #state_rcv{session = Session}, + Req = #mqtt_request{type = connect, + will_qos = 0, + will_retain = true, + keepalive = 10, + client_id = "custom-client-id"}, + {Encoded,_} = ts_mqtt:get_message(Req,State), + {#mqtt{type = Type, arg = Args}, _} = mqtt_frame:decode(Encoded), + #connect_options{client_id = ClientId} = Args, + ?assertEqual(?CONNECT, Type), + ?assertEqual("custom-client-id", ClientId). + decode_connect_test() -> Data = <<16,53,0,6,77,81,73,115,100,112,3,6,0,10,0,13,116,115,117,110, 103,45,116,101,115,116,45,105,100,0,10,119,105,108,108,95, diff --git a/src/tsung/ts_mqtt.erl b/src/tsung/ts_mqtt.erl index 4680fb815..f3e43aea2 100644 --- a/src/tsung/ts_mqtt.erl +++ b/src/tsung/ts_mqtt.erl @@ -77,12 +77,16 @@ dump(A, B) -> %% Args: record %% Returns: binary %%---------------------------------------------------------------------- +get_message(Req0 = #mqtt_request{type = connect, client_id = undefined}, StateRcv) -> + ClientId = ["tsung-", ts_utils:randombinstr(10)], + Req1 = Req0#mqtt_request{client_id = ClientId}, + get_message(Req1, StateRcv); get_message(#mqtt_request{type = connect, clean_start = CleanStart, keepalive = KeepAlive, will_topic = WillTopic, will_qos = WillQos, will_msg = WillMsg, - will_retain = WillRetain, username = UserName, password = Password}, + will_retain = WillRetain, username = UserName, + password = Password, client_id = ClientId}, #state_rcv{session = MqttSession}) -> - ClientId = ["tsung-", ts_utils:randombinstr(10)], PublishOptions = mqtt_frame:set_publish_options([{qos, WillQos}, {retain, WillRetain}]), Will = #will{topic = WillTopic, message = WillMsg, @@ -265,17 +269,19 @@ add_dynparams(true, {DynVars, _S}, keepalive = KeepAlive, will_topic = WillTopic, will_qos = WillQos, will_msg = WillMsg, will_retain = WillRetain, username = UserName, - password = Password}, + password = Password, client_id = ClientId}, _HostData) -> NewUserName = ts_search:subst(UserName, DynVars), NewPassword = ts_search:subst(Password, DynVars), + NewClientId = ts_search:subst(ClientId, DynVars), Param#mqtt_request{ type = connect, clean_start = CleanStart, keepalive = KeepAlive, will_topic = WillTopic, will_qos = WillQos, will_msg = WillMsg, will_retain = WillRetain, username = NewUserName, - password = NewPassword }; + password = NewPassword, + client_id = NewClientId}; add_dynparams(true, {DynVars, _S}, Param = #mqtt_request{type = publish, topic = Topic, payload = Payload}, diff --git a/src/tsung_controller/ts_config_mqtt.erl b/src/tsung_controller/ts_config_mqtt.erl index f73370e80..5bd0c7253 100644 --- a/src/tsung_controller/ts_config_mqtt.erl +++ b/src/tsung_controller/ts_config_mqtt.erl @@ -55,6 +55,8 @@ parse_config(Element = #xmlElement{name = mqtt}, username, undefined), Password = ts_config:getAttr(string, Element#xmlElement.attributes, password, undefined), + ClientId = ts_config:getAttr(string, Element#xmlElement.attributes, + client_id, undefined), KeepAlive = ts_config:getAttr(float_or_integer, Element#xmlElement.attributes, keepalive, 10), WillTopic = ts_config:getAttr(string, Element#xmlElement.attributes, @@ -82,7 +84,8 @@ parse_config(Element = #xmlElement{name = mqtt}, keepalive = KeepAlive, will_topic = WillTopic, will_qos = WillQos, will_msg = WillMsg, will_retain = WillRetain, topic = Topic, qos = Qos, - retained = RetainValue, payload = Payload, username = UserName, password = Password}, + retained = RetainValue, payload = Payload, username = UserName, + password = Password, client_id = ClientId}, Ack = case {Type, Qos} of {publish, 0} -> no_ack; {disconnect, _} -> no_ack; diff --git a/tsung-1.0.dtd b/tsung-1.0.dtd index 19ae9358e..631709b22 100644 --- a/tsung-1.0.dtd +++ b/tsung-1.0.dtd @@ -413,7 +413,8 @@ repeat | if | change_type | foreach | set_option | interaction | abort )*> retained CDATA "false" timeout CDATA "1" username CDATA "" - password CDATA ""> + password CDATA "" + client_id CDATA "">