@ -41,7 +41,7 @@ int handle__publish(struct mosquitto *context)
int rc2 ;
uint8_t header = context - > in_packet . command ;
int res = 0 ;
struct mosquitto__base_msg * msg, * stored = NULL ;
struct mosquitto__base_msg * base_ msg, * stored = NULL ;
size_t len ;
uint16_t slen ;
char * topic_mount ;
@ -59,73 +59,73 @@ int handle__publish(struct mosquitto *context)
context - > stats . messages_received + + ;
msg = mosquitto__calloc ( 1 , sizeof ( struct mosquitto__base_msg ) ) ;
if ( msg = = NULL ) {
base_ msg = mosquitto__calloc ( 1 , sizeof ( struct mosquitto__base_msg ) ) ;
if ( base_ msg = = NULL ) {
return MOSQ_ERR_NOMEM ;
}
dup = ( header & 0x08 ) > > 3 ;
msg- > qos = ( header & 0x06 ) > > 1 ;
if ( dup = = 1 & & msg- > qos = = 0 ) {
base_ msg- > msg . qos = ( header & 0x06 ) > > 1 ;
if ( dup = = 1 & & base_ msg- > msg . qos = = 0 ) {
log__printf ( NULL , MOSQ_LOG_INFO ,
" Invalid PUBLISH (QoS=0 and DUP=1) from %s, disconnecting. " , context - > id ) ;
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
if ( msg- > qos = = 3 ) {
if ( base_ msg- > msg . qos = = 3 ) {
log__printf ( NULL , MOSQ_LOG_INFO ,
" Invalid QoS in PUBLISH from %s, disconnecting. " , context - > id ) ;
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
if ( msg- > qos > context - > max_qos ) {
if ( base_ msg- > msg . qos > context - > max_qos ) {
log__printf ( NULL , MOSQ_LOG_INFO ,
" Too high QoS in PUBLISH from %s, disconnecting. " , context - > id ) ;
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_QOS_NOT_SUPPORTED ;
}
msg- > retain = ( header & 0x01 ) ;
base_ msg- > msg . retain = ( header & 0x01 ) ;
if ( msg- > retain & & db . config - > retain_available = = false ) {
db__msg_store_free ( msg) ;
if ( base_ msg- > msg . retain & & db . config - > retain_available = = false ) {
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_RETAIN_NOT_SUPPORTED ;
}
if ( packet__read_string ( & context - > in_packet , & msg- > topic , & slen ) ) {
db__msg_store_free ( msg) ;
if ( packet__read_string ( & context - > in_packet , & base_ msg- > msg . topic , & slen ) ) {
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
if ( ! slen & & context - > protocol ! = mosq_p_mqtt5 ) {
/* Invalid publish topic, disconnect client. */
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
if ( msg- > qos > 0 ) {
if ( base_ msg- > msg . qos > 0 ) {
if ( packet__read_uint16 ( & context - > in_packet , & mid ) ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
if ( mid = = 0 ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_PROTOCOL ;
}
/* It is important to have a separate copy of mid, because msg may be
* freed before we want to send a PUBACK / PUBREC . */
msg- > source_mid = mid ;
base_ msg- > msg . source_mid = mid ;
}
/* Handle properties */
if ( context - > protocol = = mosq_p_mqtt5 ) {
rc = property__read_all ( CMD_PUBLISH , & context - > in_packet , & properties ) ;
if ( rc ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
}
p = properties ;
p_prev = NULL ;
msg- > properties = NULL ;
base_ msg- > msg . properties = NULL ;
msg_properties_last = NULL ;
while ( p ) {
switch ( p - > identifier ) {
@ -134,11 +134,11 @@ int handle__publish(struct mosquitto *context)
case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR :
case MQTT_PROP_RESPONSE_TOPIC :
case MQTT_PROP_USER_PROPERTY :
if ( msg- > properties ) {
if ( base_ msg- > msg . properties ) {
msg_properties_last - > next = p ;
msg_properties_last = p ;
} else {
msg- > properties = p ;
base_ msg- > msg . properties = p ;
msg_properties_last = p ;
}
if ( p_prev ) {
@ -166,7 +166,7 @@ int handle__publish(struct mosquitto *context)
case MQTT_PROP_SUBSCRIPTION_IDENTIFIER :
if ( p - > value . varint = = 0 ) {
mosquitto_property_free_all ( & properties ) ;
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_PROTOCOL ;
}
p_prev = p ;
@ -182,94 +182,94 @@ int handle__publish(struct mosquitto *context)
mosquitto_property_free_all ( & properties ) ;
if ( topic_alias = = 0 | | ( context - > listener & & topic_alias > context - > listener - > max_topic_alias ) ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_TOPIC_ALIAS_INVALID ;
} else if ( topic_alias > 0 ) {
if ( msg- > topic ) {
rc = alias__add_r2l ( context , msg- > topic , ( uint16_t ) topic_alias ) ;
if ( base_ msg- > msg . topic ) {
rc = alias__add_r2l ( context , base_ msg- > msg . topic , ( uint16_t ) topic_alias ) ;
if ( rc ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
}
} else {
rc = alias__find_by_alias ( context , ALIAS_DIR_R2L , ( uint16_t ) topic_alias , & msg- > topic ) ;
rc = alias__find_by_alias ( context , ALIAS_DIR_R2L , ( uint16_t ) topic_alias , & base_ msg- > msg . topic ) ;
if ( rc ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_PROTOCOL ;
}
}
}
# ifdef WITH_BRIDGE
rc = bridge__remap_topic_in ( context , & msg- > topic ) ;
rc = bridge__remap_topic_in ( context , & base_ msg- > msg . topic ) ;
if ( rc ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
}
# endif
if ( mosquitto_pub_topic_check ( msg- > topic ) ! = MOSQ_ERR_SUCCESS ) {
if ( mosquitto_pub_topic_check ( base_ msg- > msg . topic ) ! = MOSQ_ERR_SUCCESS ) {
/* Invalid publish topic, just swallow it. */
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
msg- > payloadlen = context - > in_packet . remaining_length - context - > in_packet . pos ;
G_PUB_BYTES_RECEIVED_INC ( msg- > payloadlen ) ;
base_ msg- > msg . payloadlen = context - > in_packet . remaining_length - context - > in_packet . pos ;
G_PUB_BYTES_RECEIVED_INC ( base_ msg- > msg . payloadlen ) ;
if ( context - > listener & & context - > listener - > mount_point ) {
len = strlen ( context - > listener - > mount_point ) + strlen ( msg- > topic ) + 1 ;
len = strlen ( context - > listener - > mount_point ) + strlen ( base_ msg- > msg . topic ) + 1 ;
topic_mount = mosquitto__malloc ( len + 1 ) ;
if ( ! topic_mount ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_NOMEM ;
}
snprintf ( topic_mount , len , " %s%s " , context - > listener - > mount_point , msg- > topic ) ;
snprintf ( topic_mount , len , " %s%s " , context - > listener - > mount_point , base_ msg- > msg . topic ) ;
topic_mount [ len ] = ' \0 ' ;
mosquitto__FREE ( msg- > topic ) ;
msg- > topic = topic_mount ;
mosquitto__FREE ( base_ msg- > msg . topic ) ;
base_ msg- > msg . topic = topic_mount ;
}
if ( msg- > payloadlen ) {
if ( db . config - > message_size_limit & & msg- > payloadlen > db . config - > message_size_limit ) {
log__printf ( NULL , MOSQ_LOG_DEBUG , " Dropped too large PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " , context - > id , dup , msg- > qos, msg- > retain, msg- > source_mid, msg- > topic, ( long ) msg- > payloadlen ) ;
if ( base_ msg- > msg . payloadlen ) {
if ( db . config - > message_size_limit & & base_ msg- > msg . payloadlen > db . config - > message_size_limit ) {
log__printf ( NULL , MOSQ_LOG_DEBUG , " Dropped too large PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " , context - > id , dup , base_ msg- > msg. qos, base_ msg- > msg. retain, base_ msg- > msg. source_mid, base_ msg- > msg. topic, ( long ) base_ msg- > msg . payloadlen ) ;
reason_code = MQTT_RC_PACKET_TOO_LARGE ;
goto process_bad_message ;
}
msg- > payload = mosquitto__malloc ( msg- > payloadlen + 1 ) ;
if ( msg- > payload = = NULL ) {
db__msg_store_free ( msg) ;
base_ msg- > msg . payload = mosquitto__malloc ( base_ msg- > msg . payloadlen + 1 ) ;
if ( base_ msg- > msg . payload = = NULL ) {
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_NOMEM ;
}
/* Ensure payload is always zero terminated, this is the reason for the extra byte above */
( ( uint8_t * ) msg- > payload ) [ msg- > payloadlen ] = 0 ;
( ( uint8_t * ) base_ msg- > msg . payload ) [ base_ msg- > msg . payloadlen ] = 0 ;
if ( packet__read_bytes ( & context - > in_packet , msg- > payload , msg- > payloadlen ) ) {
db__msg_store_free ( msg) ;
if ( packet__read_bytes ( & context - > in_packet , base_ msg- > msg . payload , base_ msg- > msg . payloadlen ) ) {
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_MALFORMED_PACKET ;
}
}
/* Check for topic access */
rc = mosquitto_acl_check ( context , msg- > topic, msg- > payloadlen, msg- > payload, msg- > qos, msg- > retain , MOSQ_ACL_WRITE ) ;
rc = mosquitto_acl_check ( context , base_ msg- > msg. topic, base_ msg- > msg. payloadlen, base_ msg- > msg. payload, base_ msg- > msg. qos, base_ msg- > msg . retain , MOSQ_ACL_WRITE ) ;
if ( rc = = MOSQ_ERR_ACL_DENIED ) {
log__printf ( NULL , MOSQ_LOG_DEBUG ,
" Denied PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " ,
context - > id , dup , msg- > qos , msg- > retain , msg- > source_mid , msg- > topic ,
( long ) msg- > payloadlen ) ;
context - > id , dup , base_ msg- > msg . qos , base_ msg- > msg . retain , base_ msg- > msg . source_mid , base_ msg- > msg . topic ,
( long ) base_ msg- > msg . payloadlen ) ;
reason_code = MQTT_RC_NOT_AUTHORIZED ;
goto process_bad_message ;
} else if ( rc ! = MOSQ_ERR_SUCCESS ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
}
log__printf ( NULL , MOSQ_LOG_DEBUG , " Received PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " , context - > id , dup , msg- > qos, msg- > retain, msg- > source_mid, msg- > topic, ( long ) msg- > payloadlen ) ;
log__printf ( NULL , MOSQ_LOG_DEBUG , " Received PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " , context - > id , dup , base_ msg- > msg. qos, base_ msg- > msg. retain, base_ msg- > msg. source_mid, base_ msg- > msg. topic, ( long ) base_ msg- > msg . payloadlen ) ;
if ( ! strncmp ( msg- > topic , " $CONTROL/ " , 9 ) ) {
if ( ! strncmp ( base_ msg- > msg . topic , " $CONTROL/ " , 9 ) ) {
# ifdef WITH_CONTROL
rc = control__process ( context , msg) ;
db__msg_store_free ( msg) ;
rc = control__process ( context , base_ msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
# else
reason_code = MQTT_RC_IMPLEMENTATION_SPECIFIC ;
@ -278,12 +278,12 @@ int handle__publish(struct mosquitto *context)
}
{
rc = plugin__handle_message ( context , msg) ;
rc = plugin__handle_message ( context , base_ msg) ;
if ( rc = = MOSQ_ERR_ACL_DENIED ) {
log__printf ( NULL , MOSQ_LOG_DEBUG ,
" Denied PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) " ,
context - > id , dup , msg- > qos , msg- > retain , msg- > source_mid , msg- > topic ,
( long ) msg- > payloadlen ) ;
context - > id , dup , base_ msg- > msg . qos , base_ msg- > msg . retain , base_ msg- > msg . source_mid , base_ msg- > msg . topic ,
( long ) base_ msg- > msg . payloadlen ) ;
reason_code = MQTT_RC_NOT_AUTHORIZED ;
goto process_bad_message ;
@ -294,61 +294,61 @@ int handle__publish(struct mosquitto *context)
reason_code = MQTT_RC_QUOTA_EXCEEDED ;
goto process_bad_message ;
} else if ( rc ! = MOSQ_ERR_SUCCESS ) {
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return rc ;
}
}
if ( msg- > qos > 0 ) {
db__message_store_find ( context , msg- > source_mid , & stored ) ;
if ( base_ msg- > msg . qos > 0 ) {
db__message_store_find ( context , base_ msg- > msg . source_mid , & stored ) ;
}
if ( stored & & msg- > source_mid ! = 0 & &
( stored - > qos ! = msg- > qos
| | stored - > payloadlen ! = msg- > payloadlen
| | strcmp ( stored - > topic, msg- > topic )
| | memcmp ( stored - > payload, msg- > payload, msg- > payloadlen ) ) ) {
if ( stored & & base_ msg- > msg . source_mid ! = 0 & &
( stored - > msg. qos ! = base_ msg- > msg . qos
| | stored - > msg. payloadlen ! = base_ msg- > msg . payloadlen
| | strcmp ( stored - > msg. topic, base_ msg- > msg . topic )
| | memcmp ( stored - > msg. payload, base_ msg- > msg. payload, base_ msg- > msg . payloadlen ) ) ) {
log__printf ( NULL , MOSQ_LOG_WARNING , " Reused message ID %u from %s detected. Clearing from storage. " , msg- > source_mid , context - > id ) ;
db__message_remove_incoming ( context , msg- > source_mid ) ;
log__printf ( NULL , MOSQ_LOG_WARNING , " Reused message ID %u from %s detected. Clearing from storage. " , base_ msg- > msg . source_mid , context - > id ) ;
db__message_remove_incoming ( context , base_ msg- > msg . source_mid ) ;
stored = NULL ;
}
if ( ! stored ) {
if ( msg- > qos > 0 & & context - > msgs_in . inflight_quota = = 0 ) {
if ( base_ msg- > msg . qos > 0 & & context - > msgs_in . inflight_quota = = 0 ) {
/* Client isn't allowed any more incoming messages, so fail early */
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
return MOSQ_ERR_RECEIVE_MAXIMUM_EXCEEDED ;
}
if ( msg- > qos = = 0
| | db__ready_for_flight ( context , mosq_md_in , msg- > qos )
| | db__ready_for_queue ( context , msg- > qos , & context - > msgs_in ) ) {
if ( base_ msg- > msg . qos = = 0
| | db__ready_for_flight ( context , mosq_md_in , base_ msg- > msg . qos )
| | db__ready_for_queue ( context , base_ msg- > msg . qos , & context - > msgs_in ) ) {
dup = 0 ;
rc = db__message_store ( context , msg, message_expiry_interval , 0 , mosq_mo_client ) ;
rc = db__message_store ( context , base_ msg, message_expiry_interval , 0 , mosq_mo_client ) ;
if ( rc ) return rc ;
} else {
/* Client isn't allowed any more incoming messages, so fail early */
reason_code = MQTT_RC_QUOTA_EXCEEDED ;
goto process_bad_message ;
}
stored = msg;
msg = NULL ;
stored = base_ msg;
base_ msg = NULL ;
} else {
db__msg_store_free ( msg) ;
msg = NULL ;
db__msg_store_free ( base_ msg) ;
base_ msg = NULL ;
dup = 1 ;
}
switch ( stored - > qos) {
switch ( stored - > msg. qos) {
case 0 :
rc2 = sub__messages_queue ( context - > id , stored - > topic, stored - > qos, stored - > retain , & stored ) ;
rc2 = sub__messages_queue ( context - > id , stored - > msg. topic, stored - > msg. qos, stored - > msg . retain , & stored ) ;
if ( rc2 > 0 ) rc = 1 ;
break ;
case 1 :
util__decrement_receive_quota ( context ) ;
rc2 = sub__messages_queue ( context - > id , stored - > topic, stored - > qos, stored - > retain , & stored ) ;
rc2 = sub__messages_queue ( context - > id , stored - > msg. topic, stored - > msg. qos, stored - > msg . retain , & stored ) ;
/* stored may now be free, so don't refer to it */
if ( rc2 = = MOSQ_ERR_SUCCESS | | context - > protocol ! = mosq_p_mqtt5 ) {
if ( send__puback ( context , mid , 0 , NULL ) ) rc = 1 ;
@ -368,7 +368,7 @@ int handle__publish(struct mosquitto *context)
* due to queue . This isn ' t an error so don ' t disconnect them . */
/* FIXME - this is no longer necessary due to failing early above */
if ( ! res ) {
if ( send__pubrec ( context , stored - > source_mid, 0 , NULL ) ) rc = 1 ;
if ( send__pubrec ( context , stored - > msg. source_mid, 0 , NULL ) ) rc = 1 ;
} else if ( res = = 1 ) {
rc = 1 ;
}
@ -379,20 +379,19 @@ int handle__publish(struct mosquitto *context)
return rc ;
process_bad_message :
rc = 1 ;
if ( msg) {
switch ( msg- > qos ) {
if ( base_ msg) {
switch ( base_ msg- > msg . qos ) {
case 0 :
rc = MOSQ_ERR_SUCCESS ;
break ;
case 1 :
rc = send__puback ( context , msg- > source_mid , reason_code , NULL ) ;
rc = send__puback ( context , base_ msg- > msg . source_mid , reason_code , NULL ) ;
break ;
case 2 :
rc = send__pubrec ( context , msg- > source_mid , reason_code , NULL ) ;
rc = send__pubrec ( context , base_ msg- > msg . source_mid , reason_code , NULL ) ;
break ;
}
db__msg_store_free ( msg) ;
db__msg_store_free ( base_ msg) ;
}
return rc ;
}