1 /*
2 Copyright (c) 2009-2020 Roger Light <roger@atchoo.org>
3
4 All rights reserved. This program and the accompanying materials
5 are made available under the terms of the Eclipse Public License v1.0
6 and Eclipse Distribution License v1.0 which accompany this distribution.
7
8 The Eclipse Public License is available at
9 http://www.eclipse.org/legal/epl-v10.html
10 and the Eclipse Distribution License is available at
11 http://www.eclipse.org/org/documents/edl-v10.php.
12
13 Contributors:
14 Roger Light - initial implementation and documentation.
15 */
16
17 #include "config.h"
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #ifdef WITH_BROKER
24 # include "mosquitto_broker_internal.h"
25 # include "sys_tree.h"
26 #else
27 # define G_PUB_BYTES_SENT_INC(A)
28 #endif
29
30 #include "mosquitto.h"
31 #include "mosquitto_internal.h"
32 #include "logging_mosq.h"
33 #include "mqtt_protocol.h"
34 #include "memory_mosq.h"
35 #include "net_mosq.h"
36 #include "packet_mosq.h"
37 #include "property_mosq.h"
38 #include "send_mosq.h"
39 #include "time_mosq.h"
40 #include "util_mosq.h"
41
send__pingreq(struct mosquitto * mosq)42 int send__pingreq(struct mosquitto *mosq)
43 {
44 int rc;
45 assert(mosq);
46 #ifdef WITH_BROKER
47 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id);
48 #else
49 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id);
50 #endif
51 rc = send__simple_command(mosq, CMD_PINGREQ);
52 if(rc == MOSQ_ERR_SUCCESS){
53 mosq->ping_t = mosquitto_time();
54 }
55 return rc;
56 }
57
send__pingresp(struct mosquitto * mosq)58 int send__pingresp(struct mosquitto *mosq)
59 {
60 #ifdef WITH_BROKER
61 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id);
62 #else
63 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id);
64 #endif
65 return send__simple_command(mosq, CMD_PINGRESP);
66 }
67
send__puback(struct mosquitto * mosq,uint16_t mid,uint8_t reason_code)68 int send__puback(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code)
69 {
70 #ifdef WITH_BROKER
71 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (m%d, rc%d)", mosq->id, mid, reason_code);
72 #else
73 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (m%d, rc%d)", mosq->id, mid, reason_code);
74 #endif
75 util__increment_receive_quota(mosq);
76 /* We don't use Reason String or User Property yet. */
77 return send__command_with_mid(mosq, CMD_PUBACK, mid, false, reason_code, NULL);
78 }
79
send__pubcomp(struct mosquitto * mosq,uint16_t mid)80 int send__pubcomp(struct mosquitto *mosq, uint16_t mid)
81 {
82 #ifdef WITH_BROKER
83 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (m%d)", mosq->id, mid);
84 #else
85 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (m%d)", mosq->id, mid);
86 #endif
87 util__increment_receive_quota(mosq);
88 /* We don't use Reason String or User Property yet. */
89 return send__command_with_mid(mosq, CMD_PUBCOMP, mid, false, 0, NULL);
90 }
91
92
send__pubrec(struct mosquitto * mosq,uint16_t mid,uint8_t reason_code)93 int send__pubrec(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code)
94 {
95 #ifdef WITH_BROKER
96 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (m%d, rc%d)", mosq->id, mid, reason_code);
97 #else
98 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (m%d, rc%d)", mosq->id, mid, reason_code);
99 #endif
100 if(reason_code >= 0x80 && mosq->protocol == mosq_p_mqtt5){
101 util__increment_receive_quota(mosq);
102 }
103 /* We don't use Reason String or User Property yet. */
104 return send__command_with_mid(mosq, CMD_PUBREC, mid, false, reason_code, NULL);
105 }
106
send__pubrel(struct mosquitto * mosq,uint16_t mid)107 int send__pubrel(struct mosquitto *mosq, uint16_t mid)
108 {
109 #ifdef WITH_BROKER
110 log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (m%d)", mosq->id, mid);
111 #else
112 log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (m%d)", mosq->id, mid);
113 #endif
114 /* We don't use Reason String or User Property yet. */
115 return send__command_with_mid(mosq, CMD_PUBREL|2, mid, false, 0, NULL);
116 }
117
118 /* For PUBACK, PUBCOMP, PUBREC, and PUBREL */
send__command_with_mid(struct mosquitto * mosq,uint8_t command,uint16_t mid,bool dup,uint8_t reason_code,const mosquitto_property * properties)119 int send__command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup, uint8_t reason_code, const mosquitto_property *properties)
120 {
121 struct mosquitto__packet *packet = NULL;
122 int rc;
123 int proplen, varbytes;
124
125 assert(mosq);
126 packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet));
127 if(!packet) return MOSQ_ERR_NOMEM;
128
129 packet->command = command;
130 if(dup){
131 packet->command |= 8;
132 }
133 packet->remaining_length = 2;
134
135 if(mosq->protocol == mosq_p_mqtt5){
136 if(reason_code != 0 || properties){
137 packet->remaining_length += 1;
138 }
139
140 if(properties){
141 proplen = property__get_length_all(properties);
142 varbytes = packet__varint_bytes(proplen);
143 packet->remaining_length += varbytes + proplen;
144 }
145 }
146
147 rc = packet__alloc(packet);
148 if(rc){
149 mosquitto__free(packet);
150 return rc;
151 }
152
153 packet__write_uint16(packet, mid);
154
155 if(mosq->protocol == mosq_p_mqtt5){
156 if(reason_code != 0 || properties){
157 packet__write_byte(packet, reason_code);
158 }
159 if(properties){
160 property__write_all(packet, properties, true);
161 }
162 }
163
164 return packet__queue(mosq, packet);
165 }
166
167 /* For DISCONNECT, PINGREQ and PINGRESP */
send__simple_command(struct mosquitto * mosq,uint8_t command)168 int send__simple_command(struct mosquitto *mosq, uint8_t command)
169 {
170 struct mosquitto__packet *packet = NULL;
171 int rc;
172
173 assert(mosq);
174 packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet));
175 if(!packet) return MOSQ_ERR_NOMEM;
176
177 packet->command = command;
178 packet->remaining_length = 0;
179
180 rc = packet__alloc(packet);
181 if(rc){
182 mosquitto__free(packet);
183 return rc;
184 }
185
186 return packet__queue(mosq, packet);
187 }
188
189