Coverage Report

Created: 2023-06-07 06:10

/src/mosquitto/lib/handle_pubackcomp.c
Line
Count
Source (jump to first uncovered line)
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 <stdio.h>
23
#include <string.h>
24
25
#ifdef WITH_BROKER
26
#  include "mosquitto_broker_internal.h"
27
#endif
28
29
#include "callbacks.h"
30
#include "mosquitto.h"
31
#include "logging_mosq.h"
32
#include "memory_mosq.h"
33
#include "messages_mosq.h"
34
#include "mqtt_protocol.h"
35
#include "net_mosq.h"
36
#include "packet_mosq.h"
37
#include "read_handle.h"
38
#include "send_mosq.h"
39
#include "util_mosq.h"
40
41
42
int handle__pubackcomp(struct mosquitto *mosq, const char *type)
43
138
{
44
138
  uint8_t reason_code = 0;
45
138
  uint16_t mid;
46
138
  int rc;
47
138
  mosquitto_property *properties = NULL;
48
138
  int qos;
49
50
138
  assert(mosq);
51
52
138
  if(mosquitto__get_state(mosq) != mosq_cs_active){
53
8
    return MOSQ_ERR_PROTOCOL;
54
8
  }
55
130
  if(mosq->protocol != mosq_p_mqtt31){
56
121
    if((mosq->in_packet.command&0x0F) != 0x00){
57
9
      return MOSQ_ERR_MALFORMED_PACKET;
58
9
    }
59
121
  }
60
61
121
  pthread_mutex_lock(&mosq->msgs_out.mutex);
62
121
  util__increment_send_quota(mosq);
63
121
  pthread_mutex_unlock(&mosq->msgs_out.mutex);
64
65
121
  rc = packet__read_uint16(&mosq->in_packet, &mid);
66
121
  if(rc) return rc;
67
117
  if(type[3] == 'A'){ /* pubAck or pubComp */
68
74
    if(mosq->in_packet.command != CMD_PUBACK){
69
4
      return MOSQ_ERR_MALFORMED_PACKET;
70
4
    }
71
70
    qos = 1;
72
70
  }else{
73
43
    if(mosq->in_packet.command != CMD_PUBCOMP){
74
4
      return MOSQ_ERR_MALFORMED_PACKET;
75
4
    }
76
39
    qos = 2;
77
39
  }
78
109
  if(mid == 0){
79
1
    return MOSQ_ERR_PROTOCOL;
80
1
  }
81
82
108
  if(mosq->protocol == mosq_p_mqtt5 && mosq->in_packet.remaining_length > 2){
83
97
    rc = packet__read_byte(&mosq->in_packet, &reason_code);
84
97
    if(rc){
85
11
      return rc;
86
11
    }
87
88
86
    if(mosq->in_packet.remaining_length > 3){
89
86
      rc = property__read_all(CMD_PUBACK, &mosq->in_packet, &properties);
90
86
      if(rc) return rc;
91
86
    }
92
67
    if(type[3] == 'A'){ /* pubAck or pubComp */
93
46
      if(reason_code != MQTT_RC_SUCCESS
94
46
          && reason_code != MQTT_RC_NO_MATCHING_SUBSCRIBERS
95
46
          && reason_code != MQTT_RC_UNSPECIFIED
96
46
          && reason_code != MQTT_RC_IMPLEMENTATION_SPECIFIC
97
46
          && reason_code != MQTT_RC_NOT_AUTHORIZED
98
46
          && reason_code != MQTT_RC_TOPIC_NAME_INVALID
99
46
          && reason_code != MQTT_RC_PACKET_ID_IN_USE
100
46
          && reason_code != MQTT_RC_QUOTA_EXCEEDED
101
46
          && reason_code != MQTT_RC_PAYLOAD_FORMAT_INVALID
102
46
          ){
103
104
31
        mosquitto_property_free_all(&properties);
105
31
        return MOSQ_ERR_PROTOCOL;
106
31
      }
107
46
    }else{
108
21
      if(reason_code != MQTT_RC_SUCCESS
109
21
          && reason_code != MQTT_RC_PACKET_ID_NOT_FOUND
110
21
          ){
111
112
18
        mosquitto_property_free_all(&properties);
113
18
        return MOSQ_ERR_PROTOCOL;
114
18
      }
115
21
    }
116
67
  }
117
29
  if(mosq->in_packet.pos < mosq->in_packet.remaining_length){
118
8
    mosquitto_property_free_all(&properties);
119
8
    return MOSQ_ERR_MALFORMED_PACKET;
120
8
  }
121
122
21
#ifdef WITH_BROKER
123
21
  log__printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d, RC:%d)", type, SAFE_PRINT(mosq->id), mid, reason_code);
124
125
  /* Immediately free, we don't do anything with Reason String or User Property at the moment */
126
21
  mosquitto_property_free_all(&properties);
127
128
21
  rc = db__message_delete_outgoing(mosq, mid, mosq_ms_wait_for_pubcomp, qos);
129
21
  if(rc == MOSQ_ERR_NOT_FOUND){
130
0
    log__printf(mosq, MOSQ_LOG_WARNING, "Warning: Received %s from %s for an unknown packet identifier %d.", type, SAFE_PRINT(mosq->id), mid);
131
0
    return MOSQ_ERR_SUCCESS;
132
21
  }else{
133
21
    return rc;
134
21
  }
135
#else
136
  log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d, RC:%d)", SAFE_PRINT(mosq->id), type, mid, reason_code);
137
138
  rc = message__delete(mosq, mid, mosq_md_out, qos);
139
  if(rc == MOSQ_ERR_SUCCESS){
140
    /* Only inform the client the message has been sent once. */
141
    callback__on_publish(mosq, mid, reason_code, properties);
142
    mosquitto_property_free_all(&properties);
143
  }else{
144
    mosquitto_property_free_all(&properties);
145
146
    if(rc != MOSQ_ERR_NOT_FOUND){
147
      return rc;
148
    }
149
  }
150
151
  pthread_mutex_lock(&mosq->msgs_out.mutex);
152
  message__release_to_inflight(mosq, mosq_md_out);
153
  pthread_mutex_unlock(&mosq->msgs_out.mutex);
154
155
  return MOSQ_ERR_SUCCESS;
156
#endif
157
21
}