Coverage Report

Created: 2025-10-24 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mosquitto/lib/util_mosq.c
Line
Count
Source
1
/*
2
Copyright (c) 2009-2021 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 2.0
6
and Eclipse Distribution License v1.0 which accompany this distribution.
7
8
The Eclipse Public License is available at
9
   https://www.eclipse.org/legal/epl-2.0/
10
and the Eclipse Distribution License is available at
11
  http://www.eclipse.org/org/documents/edl-v10.php.
12
13
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
14
15
Contributors:
16
   Roger Light - initial implementation and documentation.
17
*/
18
19
#include "config.h"
20
21
#include <assert.h>
22
#include <ctype.h>
23
#include <string.h>
24
25
#ifdef WIN32
26
#  include <winsock2.h>
27
#  include <aclapi.h>
28
#  include <io.h>
29
#  include <lmcons.h>
30
#else
31
#  include <sys/stat.h>
32
#endif
33
34
#ifdef WITH_TLS
35
#  include <openssl/bn.h>
36
#endif
37
38
#ifdef WITH_BROKER
39
#include "mosquitto_broker_internal.h"
40
#else
41
#  include "callbacks.h"
42
#endif
43
44
#include "mosquitto.h"
45
#include "net_mosq.h"
46
#include "send_mosq.h"
47
#include "tls_mosq.h"
48
#include "util_mosq.h"
49
50
#if defined(WITH_WEBSOCKETS) && WITH_WEBSOCKETS == WS_IS_LWS
51
#include <libwebsockets.h>
52
#endif
53
54
55
int mosquitto__check_keepalive(struct mosquitto *mosq)
56
0
{
57
0
  time_t next_msg_out;
58
0
  time_t last_msg_in;
59
0
  time_t now;
60
#ifndef WITH_BROKER
61
  int rc;
62
#endif
63
0
  enum mosquitto_client_state state;
64
65
0
  assert(mosq);
66
0
#ifdef WITH_BROKER
67
0
  now = db.now_s;
68
#else
69
  now = mosquitto_time();
70
#endif
71
72
0
#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
73
  /* Check if a lazy bridge should be timed out due to idle. */
74
0
  if(mosq->bridge && mosq->bridge->start_type == bst_lazy
75
0
      && net__is_connected(mosq)
76
0
      && now - mosq->next_msg_out - mosq->keepalive >= mosq->bridge->idle_timeout){
77
78
0
    log__printf(mosq, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
79
0
    net__socket_close(mosq);
80
0
    return MOSQ_ERR_SUCCESS;
81
0
  }
82
0
#endif
83
0
  COMPAT_pthread_mutex_lock(&mosq->msgtime_mutex);
84
0
  next_msg_out = mosq->next_msg_out;
85
0
  last_msg_in = mosq->last_msg_in;
86
0
  COMPAT_pthread_mutex_unlock(&mosq->msgtime_mutex);
87
0
  if(mosq->keepalive && net__is_connected(mosq) &&
88
0
      (now >= next_msg_out || now - last_msg_in >= mosq->keepalive)){
89
90
0
    state = mosquitto__get_state(mosq);
91
0
    if(state == mosq_cs_active && mosq->ping_t == 0){
92
0
      send__pingreq(mosq);
93
      /* Reset last msg times to give the server time to send a pingresp */
94
0
      COMPAT_pthread_mutex_lock(&mosq->msgtime_mutex);
95
0
      mosq->last_msg_in = now;
96
0
      mosq->next_msg_out = now + mosq->keepalive;
97
0
      COMPAT_pthread_mutex_unlock(&mosq->msgtime_mutex);
98
0
    }else{
99
0
#ifdef WITH_BROKER
100
0
#  ifdef WITH_BRIDGE
101
0
      if(mosq->bridge){
102
0
        context__send_will(mosq);
103
0
      }
104
0
#  endif
105
0
      net__socket_close(mosq);
106
#else
107
      net__socket_close(mosq);
108
      state = mosquitto__get_state(mosq);
109
      if(state == mosq_cs_disconnecting){
110
        rc = MOSQ_ERR_SUCCESS;
111
      }else{
112
        rc = MOSQ_ERR_KEEPALIVE;
113
      }
114
      callback__on_disconnect(mosq, rc, NULL);
115
116
      return rc;
117
#endif
118
0
    }
119
0
  }
120
0
  return MOSQ_ERR_SUCCESS;
121
0
}
122
123
124
uint16_t mosquitto__mid_generate(struct mosquitto *mosq)
125
0
{
126
  /* FIXME - this would be better with atomic increment, but this is safer
127
   * for now for a bug fix release.
128
   *
129
   * If this is changed to use atomic increment, callers of this function
130
   * will have to be aware that they may receive a 0 result, which may not be
131
   * used as a mid.
132
   */
133
0
  uint16_t mid;
134
0
  assert(mosq);
135
136
0
  COMPAT_pthread_mutex_lock(&mosq->mid_mutex);
137
0
  mosq->last_mid++;
138
0
  if(mosq->last_mid == 0){
139
0
    mosq->last_mid++;
140
0
  }
141
0
  mid = mosq->last_mid;
142
0
  COMPAT_pthread_mutex_unlock(&mosq->mid_mutex);
143
144
0
  return mid;
145
0
}
146
147
148
#ifdef WITH_TLS
149
150
151
int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin)
152
0
{
153
0
  unsigned char *sha, tmp[SHA_DIGEST_LENGTH];
154
155
0
  if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH){
156
0
    return MOSQ_ERR_INVAL;
157
0
  }
158
159
0
  sha = mosquitto_malloc(SHA_DIGEST_LENGTH);
160
0
  if(!sha){
161
0
    return MOSQ_ERR_NOMEM;
162
0
  }
163
0
  memcpy(sha, tmp, SHA_DIGEST_LENGTH);
164
0
  *bin = sha;
165
0
  return MOSQ_ERR_SUCCESS;
166
0
}
167
168
169
int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
170
0
{
171
0
  BIGNUM *bn = NULL;
172
0
  int len;
173
0
  int leading_zero = 0;
174
0
  size_t i = 0;
175
176
  /* Count the number of leading zero */
177
0
  for(i=0; i<strlen(hex); i=i+2){
178
0
    if(strncmp(hex + i, "00", 2) == 0){
179
0
      if(leading_zero >= bin_max_len){
180
0
        return 0;
181
0
      }
182
      /* output leading zero to bin */
183
0
      bin[leading_zero] = 0;
184
0
      leading_zero++;
185
0
    }else{
186
0
      break;
187
0
    }
188
0
  }
189
190
0
  if(BN_hex2bn(&bn, hex) == 0){
191
0
    if(bn){
192
0
      BN_free(bn);
193
0
    }
194
0
    return 0;
195
0
  }
196
0
  if(BN_num_bytes(bn) + leading_zero > bin_max_len){
197
0
    BN_free(bn);
198
0
    return 0;
199
0
  }
200
201
0
  len = BN_bn2bin(bn, bin + leading_zero);
202
0
  BN_free(bn);
203
0
  return len + leading_zero;
204
0
}
205
#endif
206
207
208
void util__increment_receive_quota(struct mosquitto *mosq)
209
21
{
210
21
  if(mosq->msgs_in.inflight_quota < mosq->msgs_in.inflight_maximum){
211
0
    mosq->msgs_in.inflight_quota++;
212
0
  }
213
21
}
214
215
216
void util__increment_send_quota(struct mosquitto *mosq)
217
24
{
218
24
  if(mosq->msgs_out.inflight_quota < mosq->msgs_out.inflight_maximum){
219
0
    mosq->msgs_out.inflight_quota++;
220
0
  }
221
24
}
222
223
224
void util__decrement_receive_quota(struct mosquitto *mosq)
225
0
{
226
0
  if(mosq->msgs_in.inflight_quota > 0){
227
0
    mosq->msgs_in.inflight_quota--;
228
0
  }
229
0
}
230
231
232
void util__decrement_send_quota(struct mosquitto *mosq)
233
0
{
234
0
  if(mosq->msgs_out.inflight_quota > 0){
235
0
    mosq->msgs_out.inflight_quota--;
236
0
  }
237
0
}
238
239
240
int mosquitto__set_state(struct mosquitto *mosq, enum mosquitto_client_state state)
241
7.75k
{
242
7.75k
  COMPAT_pthread_mutex_lock(&mosq->state_mutex);
243
7.75k
#ifdef WITH_BROKER
244
7.75k
  if(mosq->state != mosq_cs_disused)
245
7.75k
#endif
246
7.75k
  {
247
7.75k
    mosq->state = state;
248
7.75k
  }
249
7.75k
  COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
250
251
7.75k
  return MOSQ_ERR_SUCCESS;
252
7.75k
}
253
254
enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq)
255
162
{
256
162
  enum mosquitto_client_state state;
257
258
162
  COMPAT_pthread_mutex_lock(&mosq->state_mutex);
259
162
  state = mosq->state;
260
162
  COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
261
262
162
  return state;
263
162
}
264
265
#ifndef WITH_BROKER
266
267
268
void mosquitto__set_request_disconnect(struct mosquitto *mosq, bool request_disconnect)
269
{
270
  COMPAT_pthread_mutex_lock(&mosq->state_mutex);
271
  mosq->request_disconnect = request_disconnect;
272
  COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
273
}
274
275
276
bool mosquitto__get_request_disconnect(struct mosquitto *mosq)
277
{
278
  bool request_disconnect;
279
280
  COMPAT_pthread_mutex_lock(&mosq->state_mutex);
281
  request_disconnect = mosq->request_disconnect;
282
  COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
283
284
  return request_disconnect;
285
}
286
#endif