mosquitto/lib/util_mosq.c

287 lines
6.2 KiB
C
Raw Normal View History

2014-05-08 00:27:00 +02:00
/*
2021-11-03 23:08:24 +01:00
Copyright (c) 2009-2021 Roger Light <roger@atchoo.org>
2014-05-08 00:27:00 +02:00
All rights reserved. This program and the accompanying materials
2020-11-25 18:34:21 +01:00
are made available under the terms of the Eclipse Public License 2.0
2014-05-08 00:27:00 +02:00
and Eclipse Distribution License v1.0 which accompany this distribution.
2018-02-13 15:16:47 +01:00
2014-05-08 00:27:00 +02:00
The Eclipse Public License is available at
2020-11-25 18:34:21 +01:00
https://www.eclipse.org/legal/epl-2.0/
2014-05-08 00:27:00 +02:00
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
2018-02-13 15:16:47 +01:00
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
2020-12-01 19:21:59 +01:00
2014-05-08 00:27:00 +02:00
Contributors:
Roger Light - initial implementation and documentation.
*/
#include "config.h"
2014-05-08 00:27:00 +02:00
#include <assert.h>
#include <ctype.h>
2014-05-08 00:27:00 +02:00
#include <string.h>
#ifdef WIN32
2017-06-26 15:53:33 +02:00
# include <winsock2.h>
# include <aclapi.h>
# include <io.h>
# include <lmcons.h>
#else
# include <sys/stat.h>
2014-05-08 00:27:00 +02:00
#endif
#ifdef WITH_TLS
# include <openssl/bn.h>
#endif
2014-05-08 00:27:00 +02:00
2018-04-16 12:48:42 +02:00
#ifdef WITH_BROKER
#include "mosquitto_broker_internal.h"
#else
# include "callbacks.h"
2018-04-16 12:48:42 +02:00
#endif
2015-04-29 22:37:47 +02:00
#include "mosquitto.h"
#include "net_mosq.h"
#include "send_mosq.h"
#include "tls_mosq.h"
#include "util_mosq.h"
2014-05-08 00:27:00 +02:00
#if defined(WITH_WEBSOCKETS) && WITH_WEBSOCKETS == WS_IS_LWS
#include <libwebsockets.h>
#endif
int mosquitto__check_keepalive(struct mosquitto *mosq)
2014-05-08 00:27:00 +02:00
{
time_t next_msg_out;
2014-05-08 00:27:00 +02:00
time_t last_msg_in;
time_t now;
2014-05-08 00:27:00 +02:00
#ifndef WITH_BROKER
int rc;
#endif
2020-12-02 11:19:18 +01:00
enum mosquitto_client_state state;
2014-05-08 00:27:00 +02:00
assert(mosq);
#ifdef WITH_BROKER
now = db.now_s;
#else
now = mosquitto_time();
#endif
2014-05-08 00:27:00 +02:00
#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
/* Check if a lazy bridge should be timed out due to idle. */
if(mosq->bridge && mosq->bridge->start_type == bst_lazy
2025-09-17 00:19:44 +02:00
&& net__is_connected(mosq)
&& now - mosq->next_msg_out - mosq->keepalive >= mosq->bridge->idle_timeout){
2014-05-08 00:27:00 +02:00
2022-12-04 00:41:15 +01:00
log__printf(mosq, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
net__socket_close(mosq);
return MOSQ_ERR_SUCCESS;
2014-05-08 00:27:00 +02:00
}
#endif
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->msgtime_mutex);
next_msg_out = mosq->next_msg_out;
2014-05-08 00:27:00 +02:00
last_msg_in = mosq->last_msg_in;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->msgtime_mutex);
2022-12-04 00:41:15 +01:00
if(mosq->keepalive && net__is_connected(mosq) &&
(now >= next_msg_out || now - last_msg_in >= mosq->keepalive)){
2014-05-08 00:27:00 +02:00
state = mosquitto__get_state(mosq);
if(state == mosq_cs_active && mosq->ping_t == 0){
2015-05-16 16:24:24 +02:00
send__pingreq(mosq);
2014-05-08 00:27:00 +02:00
/* Reset last msg times to give the server time to send a pingresp */
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->msgtime_mutex);
2014-05-08 00:27:00 +02:00
mosq->last_msg_in = now;
mosq->next_msg_out = now + mosq->keepalive;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->msgtime_mutex);
2014-05-08 00:27:00 +02:00
}else{
#ifdef WITH_BROKER
# ifdef WITH_BRIDGE
if(mosq->bridge){
context__send_will(mosq);
}
# endif
net__socket_close(mosq);
#else
2015-05-18 10:29:22 +02:00
net__socket_close(mosq);
state = mosquitto__get_state(mosq);
if(state == mosq_cs_disconnecting){
2014-05-08 00:27:00 +02:00
rc = MOSQ_ERR_SUCCESS;
}else{
rc = MOSQ_ERR_KEEPALIVE;
2014-05-08 00:27:00 +02:00
}
callback__on_disconnect(mosq, rc, NULL);
return rc;
2014-05-08 00:27:00 +02:00
#endif
}
}
return MOSQ_ERR_SUCCESS;
2014-05-08 00:27:00 +02:00
}
uint16_t mosquitto__mid_generate(struct mosquitto *mosq)
2014-05-08 00:27:00 +02:00
{
/* FIXME - this would be better with atomic increment, but this is safer
* for now for a bug fix release.
*
* If this is changed to use atomic increment, callers of this function
* will have to be aware that they may receive a 0 result, which may not be
* used as a mid.
*/
uint16_t mid;
2014-05-08 00:27:00 +02:00
assert(mosq);
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->mid_mutex);
2014-05-08 00:27:00 +02:00
mosq->last_mid++;
if(mosq->last_mid == 0){
mosq->last_mid++;
}
mid = mosq->last_mid;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->mid_mutex);
2018-02-13 15:16:47 +01:00
return mid;
2014-05-08 00:27:00 +02:00
}
#ifdef WITH_TLS
int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin)
{
unsigned char *sha, tmp[SHA_DIGEST_LENGTH];
2019-02-26 18:11:29 +01:00
if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH){
return MOSQ_ERR_INVAL;
2019-02-26 18:11:29 +01:00
}
sha = mosquitto_malloc(SHA_DIGEST_LENGTH);
if(!sha){
return MOSQ_ERR_NOMEM;
}
memcpy(sha, tmp, SHA_DIGEST_LENGTH);
*bin = sha;
return MOSQ_ERR_SUCCESS;
}
int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
2014-05-08 00:27:00 +02:00
{
BIGNUM *bn = NULL;
int len;
int leading_zero = 0;
size_t i = 0;
/* Count the number of leading zero */
2025-09-15 12:07:28 +02:00
for(i=0; i<strlen(hex); i=i+2){
if(strncmp(hex + i, "00", 2) == 0){
if(leading_zero >= bin_max_len){
return 0;
}
/* output leading zero to bin */
bin[leading_zero] = 0;
leading_zero++;
}else{
break;
}
}
2014-05-08 00:27:00 +02:00
if(BN_hex2bn(&bn, hex) == 0){
if(bn){
BN_free(bn);
}
2014-05-08 00:27:00 +02:00
return 0;
}
if(BN_num_bytes(bn) + leading_zero > bin_max_len){
2014-05-08 00:27:00 +02:00
BN_free(bn);
return 0;
}
len = BN_bn2bin(bn, bin + leading_zero);
2014-05-08 00:27:00 +02:00
BN_free(bn);
return len + leading_zero;
2014-05-08 00:27:00 +02:00
}
#endif
2019-01-08 13:27:19 +01:00
void util__increment_receive_quota(struct mosquitto *mosq)
{
if(mosq->msgs_in.inflight_quota < mosq->msgs_in.inflight_maximum){
mosq->msgs_in.inflight_quota++;
2019-01-08 13:27:19 +01:00
}
}
void util__increment_send_quota(struct mosquitto *mosq)
{
if(mosq->msgs_out.inflight_quota < mosq->msgs_out.inflight_maximum){
mosq->msgs_out.inflight_quota++;
}
}
void util__decrement_receive_quota(struct mosquitto *mosq)
{
if(mosq->msgs_in.inflight_quota > 0){
mosq->msgs_in.inflight_quota--;
}
}
void util__decrement_send_quota(struct mosquitto *mosq)
{
if(mosq->msgs_out.inflight_quota > 0){
mosq->msgs_out.inflight_quota--;
}
2019-02-26 19:51:31 +01:00
}
int mosquitto__set_state(struct mosquitto *mosq, enum mosquitto_client_state state)
{
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->state_mutex);
#ifdef WITH_BROKER
if(mosq->state != mosq_cs_disused)
#endif
{
mosq->state = state;
}
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
return MOSQ_ERR_SUCCESS;
}
enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq)
{
enum mosquitto_client_state state;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->state_mutex);
state = mosq->state;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
return state;
}
#ifndef WITH_BROKER
void mosquitto__set_request_disconnect(struct mosquitto *mosq, bool request_disconnect)
{
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->state_mutex);
mosq->request_disconnect = request_disconnect;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
}
bool mosquitto__get_request_disconnect(struct mosquitto *mosq)
{
bool request_disconnect;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_lock(&mosq->state_mutex);
request_disconnect = mosq->request_disconnect;
2024-10-12 18:00:40 +02:00
COMPAT_pthread_mutex_unlock(&mosq->state_mutex);
return request_disconnect;
}
#endif