2016-03-06 23:30:17 +01:00
|
|
|
/*
|
2021-11-03 23:08:24 +01:00
|
|
|
Copyright (c) 2009-2021 Roger Light <roger@atchoo.org>
|
2016-03-06 23:30:17 +01: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
|
2016-03-06 23:30:17 +01:00
|
|
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
|
|
|
|
|
|
|
|
The Eclipse Public License is available at
|
2020-11-25 18:34:21 +01:00
|
|
|
https://www.eclipse.org/legal/epl-2.0/
|
2016-03-06 23:30:17 +01:00
|
|
|
and the Eclipse Distribution License is available at
|
|
|
|
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
|
|
|
|
|
2021-01-20 12:46:18 +01:00
|
|
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
2020-12-01 19:21:59 +01:00
|
|
|
|
2016-03-06 23:30:17 +01:00
|
|
|
Contributors:
|
|
|
|
|
Roger Light - initial implementation and documentation.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-08-16 12:14:51 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
|
2016-03-06 23:30:17 +01:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2018-04-16 12:48:42 +02:00
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
# include "mosquitto_broker_internal.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-03-13 18:30:13 +01:00
|
|
|
#include "callbacks.h"
|
2016-03-06 23:30:17 +01:00
|
|
|
#include "mosquitto.h"
|
|
|
|
|
#include "logging_mosq.h"
|
|
|
|
|
#include "messages_mosq.h"
|
2023-12-23 13:59:58 +01:00
|
|
|
#include "mosquitto/mqtt_protocol.h"
|
2016-03-06 23:30:17 +01:00
|
|
|
#include "net_mosq.h"
|
|
|
|
|
#include "packet_mosq.h"
|
|
|
|
|
#include "read_handle.h"
|
|
|
|
|
#include "send_mosq.h"
|
|
|
|
|
#include "util_mosq.h"
|
|
|
|
|
|
|
|
|
|
|
2020-11-06 16:16:07 +01:00
|
|
|
int handle__pubrel(struct mosquitto *mosq)
|
2016-03-06 23:30:17 +01:00
|
|
|
{
|
2018-12-23 22:49:39 +01:00
|
|
|
uint8_t reason_code;
|
2016-03-06 23:30:17 +01:00
|
|
|
uint16_t mid;
|
|
|
|
|
#ifndef WITH_BROKER
|
|
|
|
|
struct mosquitto_message_all *message = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
int rc;
|
2018-11-02 00:50:54 +01:00
|
|
|
mosquitto_property *properties = NULL;
|
2016-03-06 23:30:17 +01:00
|
|
|
|
|
|
|
|
assert(mosq);
|
2019-04-03 21:46:21 +02:00
|
|
|
|
2020-12-02 11:19:18 +01:00
|
|
|
if(mosquitto__get_state(mosq) != mosq_cs_active){
|
2025-11-26 15:31:50 +01:00
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: PUBREL before session is active.", mosq->id);
|
|
|
|
|
#endif
|
2019-04-03 21:46:21 +02:00
|
|
|
return MOSQ_ERR_PROTOCOL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-30 22:14:38 +02:00
|
|
|
if(mosq->protocol != mosq_p_mqtt31){
|
2016-03-06 23:30:17 +01:00
|
|
|
if((mosq->in_packet.command&0x0F) != 0x02){
|
2025-11-26 15:31:50 +01:00
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: PUBREL with non-zero reserved flags (%02X).",
|
|
|
|
|
mosq->id, mosq->in_packet.command);
|
|
|
|
|
#endif
|
2016-03-06 23:30:17 +01:00
|
|
|
return MOSQ_ERR_PROTOCOL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rc = packet__read_uint16(&mosq->in_packet, &mid);
|
2025-09-17 09:56:58 +02:00
|
|
|
if(rc){
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
if(mid == 0){
|
2025-11-26 15:31:50 +01:00
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: PUBREL with mid = 0.",
|
|
|
|
|
mosq->id);
|
|
|
|
|
#endif
|
2025-09-17 09:56:58 +02:00
|
|
|
return MOSQ_ERR_PROTOCOL;
|
|
|
|
|
}
|
2018-10-25 13:03:22 +02:00
|
|
|
|
2019-01-17 17:52:44 +01:00
|
|
|
if(mosq->protocol == mosq_p_mqtt5 && mosq->in_packet.remaining_length > 2){
|
2018-12-23 22:49:39 +01:00
|
|
|
rc = packet__read_byte(&mosq->in_packet, &reason_code);
|
2025-09-17 09:56:58 +02:00
|
|
|
if(rc){
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
2018-12-23 22:49:39 +01:00
|
|
|
|
2021-06-16 22:48:57 +02:00
|
|
|
if(reason_code != MQTT_RC_SUCCESS && reason_code != MQTT_RC_PACKET_ID_NOT_FOUND){
|
2025-11-26 15:31:50 +01:00
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: PUBREL with reason code = %d.",
|
|
|
|
|
mosq->id, reason_code);
|
|
|
|
|
#endif
|
2021-06-16 22:48:57 +02:00
|
|
|
return MOSQ_ERR_PROTOCOL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-17 17:52:44 +01:00
|
|
|
if(mosq->in_packet.remaining_length > 3){
|
|
|
|
|
rc = property__read_all(CMD_PUBREL, &mosq->in_packet, &properties);
|
2022-03-23 23:09:50 +01:00
|
|
|
/* Immediately free, we don't do anything with Reason String or
|
|
|
|
|
* User Property at the moment */
|
|
|
|
|
mosquitto_property_free_all(&properties);
|
2025-11-26 15:31:50 +01:00
|
|
|
if(rc){
|
|
|
|
|
if(rc == MOSQ_ERR_PROTOCOL){
|
|
|
|
|
#ifdef WITH_BROKER
|
|
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: PUBREL with invalid properties.", mosq->id);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
2019-01-17 17:52:44 +01:00
|
|
|
}
|
2018-10-25 13:03:22 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-16 22:48:57 +02:00
|
|
|
if(mosq->in_packet.pos < mosq->in_packet.remaining_length){
|
|
|
|
|
return MOSQ_ERR_MALFORMED_PACKET;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 23:30:17 +01:00
|
|
|
#ifdef WITH_BROKER
|
2021-11-15 23:29:19 +01:00
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", SAFE_PRINT(mosq->id), mid);
|
2016-03-06 23:30:17 +01:00
|
|
|
|
2020-11-06 16:16:07 +01:00
|
|
|
rc = db__message_release_incoming(mosq, mid);
|
2019-07-31 19:37:59 +02:00
|
|
|
if(rc == MOSQ_ERR_NOT_FOUND){
|
2016-03-06 23:30:17 +01:00
|
|
|
/* Message not found. Still send a PUBCOMP anyway because this could be
|
|
|
|
|
* due to a repeated PUBREL after a client has reconnected. */
|
2019-07-31 19:37:59 +02:00
|
|
|
}else if(rc != MOSQ_ERR_SUCCESS){
|
|
|
|
|
return rc;
|
2016-03-06 23:30:17 +01:00
|
|
|
}
|
2019-01-17 17:52:44 +01:00
|
|
|
|
2020-07-10 12:03:29 +02:00
|
|
|
rc = send__pubcomp(mosq, mid, NULL);
|
2025-09-17 09:56:58 +02:00
|
|
|
if(rc){
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
2016-03-06 23:30:17 +01:00
|
|
|
#else
|
2021-11-15 23:29:19 +01:00
|
|
|
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", SAFE_PRINT(mosq->id), mid);
|
2016-03-06 23:30:17 +01:00
|
|
|
|
2020-07-10 12:03:29 +02:00
|
|
|
rc = send__pubcomp(mosq, mid, NULL);
|
2019-01-17 17:52:44 +01:00
|
|
|
if(rc){
|
2019-02-12 18:05:42 +01:00
|
|
|
message__remove(mosq, mid, mosq_md_in, &message, 2);
|
2019-01-17 17:52:44 +01:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-23 12:44:19 +01:00
|
|
|
rc = message__remove(mosq, mid, mosq_md_in, &message, 2);
|
2020-03-19 16:38:29 +01:00
|
|
|
if(rc == MOSQ_ERR_SUCCESS){
|
2016-03-06 23:30:17 +01:00
|
|
|
/* Only pass the message on if we have removed it from the queue - this
|
|
|
|
|
* prevents multiple callbacks for the same message. */
|
2021-03-13 18:30:13 +01:00
|
|
|
callback__on_message(mosq, &message->msg, message->properties);
|
2016-03-06 23:30:17 +01:00
|
|
|
message__cleanup(&message);
|
2020-03-19 16:38:29 +01:00
|
|
|
}else if(rc == MOSQ_ERR_NOT_FOUND){
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
|
}else{
|
|
|
|
|
return rc;
|
2016-03-06 23:30:17 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
|
}
|