1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | #include <assert.h>
|
31 | #include <string.h>
|
32 |
|
33 | #ifdef WIN32
|
34 | #include <winsock2.h>
|
35 | #endif
|
36 |
|
37 |
|
38 | #include "mosquitto.h"
|
39 | #include "memory_mosq.h"
|
40 | #include "net_mosq.h"
|
41 | #include "send_mosq.h"
|
42 | #include "time_mosq.h"
|
43 | #include "tls_mosq.h"
|
44 | #include "util_mosq.h"
|
45 |
|
46 | #ifdef WITH_BROKER
|
47 | #include "mosquitto_broker.h"
|
48 | #endif
|
49 |
|
50 | int _mosquitto_packet_alloc(struct _mosquitto_packet *packet)
|
51 | {
|
52 | uint8_t remaining_bytes[5], byte;
|
53 | uint32_t remaining_length;
|
54 | int i;
|
55 |
|
56 | assert(packet);
|
57 |
|
58 | remaining_length = packet->remaining_length;
|
59 | packet->payload = NULL;
|
60 | packet->remaining_count = 0;
|
61 | do{
|
62 | byte = remaining_length % 128;
|
63 | remaining_length = remaining_length / 128;
|
64 |
|
65 | if(remaining_length > 0){
|
66 | byte = byte | 0x80;
|
67 | }
|
68 | remaining_bytes[packet->remaining_count] = byte;
|
69 | packet->remaining_count++;
|
70 | }while(remaining_length > 0 && packet->remaining_count < 5);
|
71 | if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE;
|
72 | packet->packet_length = packet->remaining_length + 1 + packet->remaining_count;
|
73 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
|
74 | if(!packet->payload) return MOSQ_ERR_NOMEM;
|
75 |
|
76 | packet->payload[0] = packet->command;
|
77 | for(i=0; i<packet->remaining_count; i++){
|
78 | packet->payload[i+1] = remaining_bytes[i];
|
79 | }
|
80 | packet->pos = 1 + packet->remaining_count;
|
81 |
|
82 | return MOSQ_ERR_SUCCESS;
|
83 | }
|
84 |
|
85 | void _mosquitto_check_keepalive(struct mosquitto *mosq)
|
86 | {
|
87 | time_t last_msg_out;
|
88 | time_t last_msg_in;
|
89 | time_t now = mosquitto_time();
|
90 | #ifndef WITH_BROKER
|
91 | int rc;
|
92 | #endif
|
93 |
|
94 | assert(mosq);
|
95 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
|
96 |
|
97 | if(mosq->bridge && mosq->bridge->start_type == bst_lazy
|
98 | && mosq->sock != INVALID_SOCKET
|
99 | && now - mosq->last_msg_out >= mosq->bridge->idle_timeout){
|
100 |
|
101 | _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
|
102 | _mosquitto_socket_close(mosq);
|
103 | return;
|
104 | }
|
105 | #endif
|
106 | pthread_mutex_lock(&mosq->msgtime_mutex);
|
107 | last_msg_out = mosq->last_msg_out;
|
108 | last_msg_in = mosq->last_msg_in;
|
109 | pthread_mutex_unlock(&mosq->msgtime_mutex);
|
110 | if(mosq->keepalive && mosq->sock != INVALID_SOCKET &&
|
111 | (now - last_msg_out >= mosq->keepalive || now - last_msg_in >= mosq->keepalive)){
|
112 |
|
113 | if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){
|
114 | _mosquitto_send_pingreq(mosq);
|
115 |
|
116 | pthread_mutex_lock(&mosq->msgtime_mutex);
|
117 | mosq->last_msg_in = now;
|
118 | mosq->last_msg_out = now;
|
119 | pthread_mutex_unlock(&mosq->msgtime_mutex);
|
120 | }else{
|
121 | #ifdef WITH_BROKER
|
122 | if(mosq->listener){
|
123 | mosq->listener->client_count--;
|
124 | assert(mosq->listener->client_count >= 0);
|
125 | }
|
126 | mosq->listener = NULL;
|
127 | #endif
|
128 | _mosquitto_socket_close(mosq);
|
129 | #ifndef WITH_BROKER
|
130 | pthread_mutex_lock(&mosq->state_mutex);
|
131 | if(mosq->state == mosq_cs_disconnecting){
|
132 | rc = MOSQ_ERR_SUCCESS;
|
133 | }else{
|
134 | rc = 1;
|
135 | }
|
136 | pthread_mutex_unlock(&mosq->state_mutex);
|
137 | pthread_mutex_lock(&mosq->callback_mutex);
|
138 | if(mosq->on_disconnect){
|
139 | mosq->in_callback = true;
|
140 | mosq->on_disconnect(mosq, mosq->userdata, rc);
|
141 | mosq->in_callback = false;
|
142 | }
|
143 | pthread_mutex_unlock(&mosq->callback_mutex);
|
144 | #endif
|
145 | }
|
146 | }
|
147 | }
|
148 |
|
149 | uint16_t _mosquitto_mid_generate(struct mosquitto *mosq)
|
150 | {
|
151 | assert(mosq);
|
152 |
|
153 | mosq->last_mid++;
|
154 | if(mosq->last_mid == 0) mosq->last_mid++;
|
155 |
|
156 | return mosq->last_mid;
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 | int _mosquitto_topic_wildcard_len_check(const char *str)
|
164 | {
|
165 | int len = 0;
|
166 | while(str && str[0]){
|
167 | if(str[0] == '+' || str[0] == '#'){
|
168 | return MOSQ_ERR_INVAL;
|
169 | }
|
170 | len++;
|
171 | str = &str[1];
|
172 | }
|
173 | if(len > 65535) return MOSQ_ERR_INVAL;
|
174 |
|
175 | return MOSQ_ERR_SUCCESS;
|
176 | }
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 | int _mosquitto_topic_wildcard_pos_check(const char *str)
|
184 | {
|
185 | char c = '\0';
|
186 | int len = 0;
|
187 | while(str && str[0]){
|
188 | if(str[0] == '+'){
|
189 | if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
|
190 | return MOSQ_ERR_INVAL;
|
191 | }
|
192 | }else if(str[0] == '#'){
|
193 | if((c != '\0' && c != '/') || str[1] != '\0'){
|
194 | return MOSQ_ERR_INVAL;
|
195 | }
|
196 | }
|
197 | len++;
|
198 | c = str[0];
|
199 | str = &str[1];
|
200 | }
|
201 | if(len > 65535) return MOSQ_ERR_INVAL;
|
202 |
|
203 | return MOSQ_ERR_SUCCESS;
|
204 | }
|
205 |
|
206 |
|
207 | int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
|
208 | {
|
209 | int slen, tlen;
|
210 | int spos, tpos;
|
211 | bool multilevel_wildcard = false;
|
212 |
|
213 | if(!sub || !topic || !result) return MOSQ_ERR_INVAL;
|
214 |
|
215 | slen = strlen(sub);
|
216 | tlen = strlen(topic);
|
217 |
|
218 | if(slen && tlen){
|
219 | if((sub[0] == '$' && topic[0] != '$')
|
220 | || (topic[0] == '$' && sub[0] != '$')){
|
221 |
|
222 | *result = false;
|
223 | return MOSQ_ERR_SUCCESS;
|
224 | }
|
225 | }
|
226 |
|
227 | spos = 0;
|
228 | tpos = 0;
|
229 |
|
230 | while(spos < slen && tpos < tlen){
|
231 | if(sub[spos] == topic[tpos]){
|
232 | spos++;
|
233 | tpos++;
|
234 | if(spos == slen && tpos == tlen){
|
235 | *result = true;
|
236 | return MOSQ_ERR_SUCCESS;
|
237 | }else if(tpos == tlen && spos == slen-1 && sub[spos] == '+'){
|
238 | spos++;
|
239 | *result = true;
|
240 | return MOSQ_ERR_SUCCESS;
|
241 | }
|
242 | }else{
|
243 | if(sub[spos] == '+'){
|
244 | spos++;
|
245 | while(tpos < tlen && topic[tpos] != '/'){
|
246 | tpos++;
|
247 | }
|
248 | if(tpos == tlen && spos == slen){
|
249 | *result = true;
|
250 | return MOSQ_ERR_SUCCESS;
|
251 | }
|
252 | }else if(sub[spos] == '#'){
|
253 | multilevel_wildcard = true;
|
254 | if(spos+1 != slen){
|
255 | *result = false;
|
256 | return MOSQ_ERR_SUCCESS;
|
257 | }else{
|
258 | *result = true;
|
259 | return MOSQ_ERR_SUCCESS;
|
260 | }
|
261 | }else{
|
262 | *result = false;
|
263 | return MOSQ_ERR_SUCCESS;
|
264 | }
|
265 | }
|
266 | if(tpos == tlen-1){
|
267 |
|
268 | if(spos == slen-3
|
269 | && sub[spos+1] == '/'
|
270 | && sub[spos+2] == '#'){
|
271 | *result = true;
|
272 | multilevel_wildcard = true;
|
273 | return MOSQ_ERR_SUCCESS;
|
274 | }
|
275 | }
|
276 | }
|
277 | if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){
|
278 | *result = false;
|
279 | }
|
280 |
|
281 | return MOSQ_ERR_SUCCESS;
|
282 | }
|
283 |
|
284 | #ifdef REAL_WITH_TLS_PSK
|
285 | int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
|
286 | {
|
287 | BIGNUM *bn = NULL;
|
288 | int len;
|
289 |
|
290 | if(BN_hex2bn(&bn, hex) == 0){
|
291 | if(bn) BN_free(bn);
|
292 | return 0;
|
293 | }
|
294 | if(BN_num_bytes(bn) > bin_max_len){
|
295 | BN_free(bn);
|
296 | return 0;
|
297 | }
|
298 |
|
299 | len = BN_bn2bin(bn, bin);
|
300 | BN_free(bn);
|
301 | return len;
|
302 | }
|
303 | #endif
|
304 |
|
305 | FILE *_mosquitto_fopen(const char *path, const char *mode)
|
306 | {
|
307 | #ifdef WIN32
|
308 | char buf[MAX_PATH];
|
309 | int rc;
|
310 | rc = ExpandEnvironmentStrings(path, buf, MAX_PATH);
|
311 | if(rc == 0 || rc == MAX_PATH){
|
312 | return NULL;
|
313 | }else{
|
314 | return fopen(buf, mode);
|
315 | }
|
316 | #else
|
317 | return fopen(path, mode);
|
318 | #endif
|
319 | }
|
320 |
|