send_connect.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. Copyright (c) 2009-2020 Roger Light <roger@atchoo.org>
  3. All rights reserved. This program and the accompanying materials
  4. are made available under the terms of the Eclipse Public License 2.0
  5. and Eclipse Distribution License v1.0 which accompany this distribution.
  6. The Eclipse Public License is available at
  7. https://www.eclipse.org/legal/epl-2.0/
  8. and the Eclipse Distribution License is available at
  9. http://www.eclipse.org/org/documents/edl-v10.php.
  10. SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
  11. Contributors:
  12. Roger Light - initial implementation and documentation.
  13. */
  14. #include "config.h"
  15. #include <assert.h>
  16. #include <string.h>
  17. #ifdef WITH_BROKER
  18. # include "mosquitto_broker_internal.h"
  19. #endif
  20. #include "logging_mosq.h"
  21. #include "memory_mosq.h"
  22. #include "mosquitto.h"
  23. #include "mosquitto_internal.h"
  24. #include "mqtt_protocol.h"
  25. #include "packet_mosq.h"
  26. #include "property_mosq.h"
  27. #include "send_mosq.h"
  28. int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session, const mosquitto_property *properties)
  29. {
  30. struct mosquitto__packet *packet = NULL;
  31. uint32_t payloadlen;
  32. uint8_t will = 0;
  33. uint8_t byte;
  34. int rc;
  35. uint8_t version;
  36. char *clientid, *username, *password;
  37. uint32_t headerlen;
  38. uint32_t proplen = 0, varbytes;
  39. mosquitto_property *local_props = NULL;
  40. uint16_t receive_maximum;
  41. assert(mosq);
  42. if(mosq->protocol == mosq_p_mqtt31 && !mosq->id) return MOSQ_ERR_PROTOCOL;
  43. #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
  44. if(mosq->bridge){
  45. clientid = mosq->bridge->remote_clientid;
  46. username = mosq->bridge->remote_username;
  47. password = mosq->bridge->remote_password;
  48. }else{
  49. clientid = mosq->id;
  50. username = mosq->username;
  51. password = mosq->password;
  52. }
  53. #else
  54. clientid = mosq->id;
  55. username = mosq->username;
  56. password = mosq->password;
  57. #endif
  58. if(mosq->protocol == mosq_p_mqtt5){
  59. /* Generate properties from options */
  60. if(!mosquitto_property_read_int16(properties, MQTT_PROP_RECEIVE_MAXIMUM, &receive_maximum, false)){
  61. rc = mosquitto_property_add_int16(&local_props, MQTT_PROP_RECEIVE_MAXIMUM, mosq->msgs_in.inflight_maximum);
  62. if(rc) return rc;
  63. }else{
  64. mosq->msgs_in.inflight_maximum = receive_maximum;
  65. mosq->msgs_in.inflight_quota = receive_maximum;
  66. }
  67. version = MQTT_PROTOCOL_V5;
  68. headerlen = 10;
  69. proplen = 0;
  70. proplen += property__get_length_all(properties);
  71. proplen += property__get_length_all(local_props);
  72. varbytes = packet__varint_bytes(proplen);
  73. headerlen += proplen + varbytes;
  74. }else if(mosq->protocol == mosq_p_mqtt311){
  75. version = MQTT_PROTOCOL_V311;
  76. headerlen = 10;
  77. }else if(mosq->protocol == mosq_p_mqtt31){
  78. version = MQTT_PROTOCOL_V31;
  79. headerlen = 12;
  80. }else{
  81. return MOSQ_ERR_INVAL;
  82. }
  83. packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet));
  84. if(!packet) return MOSQ_ERR_NOMEM;
  85. if(clientid){
  86. payloadlen = (uint32_t)(2U+strlen(clientid));
  87. }else{
  88. payloadlen = 2U;
  89. }
  90. #ifdef WITH_BROKER
  91. if(mosq->will && (mosq->bridge == NULL || mosq->bridge->notifications_local_only == false)){
  92. #else
  93. if(mosq->will){
  94. #endif
  95. will = 1;
  96. assert(mosq->will->msg.topic);
  97. payloadlen += (uint32_t)(2+strlen(mosq->will->msg.topic) + 2+(uint32_t)mosq->will->msg.payloadlen);
  98. if(mosq->protocol == mosq_p_mqtt5){
  99. payloadlen += property__get_remaining_length(mosq->will->properties);
  100. }
  101. }
  102. /* After this check we can be sure that the username and password are
  103. * always valid for the current protocol, so there is no need to check
  104. * username before checking password. */
  105. if(mosq->protocol == mosq_p_mqtt31 || mosq->protocol == mosq_p_mqtt311){
  106. if(password != NULL && username == NULL){
  107. mosquitto__free(packet);
  108. return MOSQ_ERR_INVAL;
  109. }
  110. }
  111. if(username){
  112. payloadlen += (uint32_t)(2+strlen(username));
  113. }
  114. if(password){
  115. payloadlen += (uint32_t)(2+strlen(password));
  116. }
  117. packet->command = CMD_CONNECT;
  118. packet->remaining_length = headerlen + payloadlen;
  119. rc = packet__alloc(packet);
  120. if(rc){
  121. mosquitto__free(packet);
  122. return rc;
  123. }
  124. /* Variable header */
  125. if(version == MQTT_PROTOCOL_V31){
  126. packet__write_string(packet, PROTOCOL_NAME_v31, (uint16_t)strlen(PROTOCOL_NAME_v31));
  127. }else{
  128. packet__write_string(packet, PROTOCOL_NAME, (uint16_t)strlen(PROTOCOL_NAME));
  129. }
  130. #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
  131. if(mosq->bridge && mosq->bridge->protocol_version != mosq_p_mqtt5 && mosq->bridge->try_private && mosq->bridge->try_private_accepted){
  132. version |= 0x80;
  133. }else{
  134. }
  135. #endif
  136. packet__write_byte(packet, version);
  137. byte = (uint8_t)((clean_session&0x1)<<1);
  138. if(will){
  139. byte = byte | (uint8_t)(((mosq->will->msg.qos&0x3)<<3) | ((will&0x1)<<2));
  140. if(mosq->retain_available){
  141. byte |= (uint8_t)((mosq->will->msg.retain&0x1)<<5);
  142. }
  143. }
  144. if(username){
  145. byte = byte | 0x1<<7;
  146. }
  147. if(mosq->password){
  148. byte = byte | 0x1<<6;
  149. }
  150. packet__write_byte(packet, byte);
  151. packet__write_uint16(packet, keepalive);
  152. if(mosq->protocol == mosq_p_mqtt5){
  153. /* Write properties */
  154. packet__write_varint(packet, proplen);
  155. property__write_all(packet, properties, false);
  156. property__write_all(packet, local_props, false);
  157. }
  158. mosquitto_property_free_all(&local_props);
  159. /* Payload */
  160. if(clientid){
  161. packet__write_string(packet, clientid, (uint16_t)strlen(clientid));
  162. }else{
  163. packet__write_uint16(packet, 0);
  164. }
  165. if(will){
  166. if(mosq->protocol == mosq_p_mqtt5){
  167. /* Write will properties */
  168. property__write_all(packet, mosq->will->properties, true);
  169. }
  170. packet__write_string(packet, mosq->will->msg.topic, (uint16_t)strlen(mosq->will->msg.topic));
  171. packet__write_string(packet, (const char *)mosq->will->msg.payload, (uint16_t)mosq->will->msg.payloadlen);
  172. }
  173. if(username){
  174. packet__write_string(packet, username, (uint16_t)strlen(username));
  175. }
  176. if(password){
  177. packet__write_string(packet, password, (uint16_t)strlen(password));
  178. }
  179. mosq->keepalive = keepalive;
  180. #ifdef WITH_BROKER
  181. # ifdef WITH_BRIDGE
  182. log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", clientid);
  183. # endif
  184. #else
  185. log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", clientid);
  186. #endif
  187. return packet__queue(mosq, packet);
  188. }