int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos) { /* FIXME - only deals with a single topic */ struct _mosquitto_packet *packet = NULL; uint32_t packetlen; uint16_t local_mid; int rc; assert(mosq); assert(topic); packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); if(!packet) return MOSQ_ERR_NOMEM; packetlen = 2 + 2+strlen(topic) + 1; packet->command = SUBSCRIBE | (dup<<3) | (1<<1); packet->remaining_length = packetlen; rc = _mosquitto_packet_alloc(packet); if(rc){ _mosquitto_free(packet); return rc; } /* Variable header */ local_mid = _mosquitto_mid_generate(mosq); if(mid) *mid = (int)local_mid; _mosquitto_write_uint16(packet, local_mid); /* Payload */ _mosquitto_write_string(packet, topic, strlen(topic)); _mosquitto_write_byte(packet, topic_qos); #ifdef WITH_BROKER # ifdef WITH_BRIDGE _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos); # endif #else _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos); #endif return _mosquitto_packet_queue(mosq, packet); }
static int _retain_process(struct mosquitto_db *db, struct mosquitto_msg_store *retained, struct mosquitto *context, const char *sub, int sub_qos) { int rc = 0; int qos; uint16_t mid; rc = mosquitto_acl_check(db, context, retained->msg.topic, MOSQ_ACL_READ); if(rc == MOSQ_ERR_ACL_DENIED){ return MOSQ_ERR_SUCCESS; }else if(rc != MOSQ_ERR_SUCCESS){ return rc; } qos = retained->msg.qos; if(qos > sub_qos) qos = sub_qos; if(qos > 0){ mid = _mosquitto_mid_generate(context); }else{ mid = 0; } return mqtt3_db_message_insert(db, context, mid, mosq_md_out, qos, true, retained); }
int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain) { struct mosquitto_message_all *message; uint16_t local_mid; int queue_status; if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL; if(STREMPTY(topic)) return MOSQ_ERR_INVAL; if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ return MOSQ_ERR_INVAL; } local_mid = _mosquitto_mid_generate(mosq); if(mid){ *mid = local_mid; } if(qos == 0){ return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false); }else{ message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); if(!message) return MOSQ_ERR_NOMEM; message->next = NULL; message->timestamp = mosquitto_time(); message->msg.mid = local_mid; message->msg.topic = _mosquitto_strdup(topic); if(!message->msg.topic){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } if(payloadlen){ message->msg.payloadlen = payloadlen; message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t)); if(!message->msg.payload){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); }else{ message->msg.payloadlen = 0; message->msg.payload = NULL; } message->msg.qos = qos; message->msg.retain = retain; message->dup = false; pthread_mutex_lock(&mosq->out_message_mutex); printf("================ mosquitto.c ================\n"); printf("#mosq->inflight_messages : %s\n", mosq->inflight_messages); queue_status = _mosquitto_message_queue(mosq, message, mosq_md_out); if(queue_status == 0){ if(qos == 1){ message->state = mosq_ms_wait_for_puback; }else if(qos == 2){ message->state = mosq_ms_wait_for_pubrec; } pthread_mutex_unlock(&mosq->out_message_mutex); return _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); }else{ message->state = mosq_ms_invalid; pthread_mutex_unlock(&mosq->out_message_mutex); return MOSQ_ERR_SUCCESS; } } }
/* 整个.c文件就是处理客户端的连接请求,返回一个连接确认包 */ int mqtt3_handle_connack(struct mosquitto_db *db, struct mosquitto *context) { uint8_t byte; uint8_t rc; int i; char *notification_topic; int notification_topic_len; char notification_payload; if(!context){ return MOSQ_ERR_INVAL; } #ifdef WITH_STRICT_PROTOCOL if(context->in_packet.remaining_length != 2){ return MOSQ_ERR_PROTOCOL; } #endif _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received CONNACK on connection %s.", context->id); if(_mosquitto_read_byte(&context->in_packet, &byte)) return 1; // Reserved byte, not used if(_mosquitto_read_byte(&context->in_packet, &rc)) return 1; switch(rc){ // case CONNACK_ACCEPTED: // 这是一个broker客户端 if(context->bridge){ // 提醒机制是怎么做的? if(context->bridge->notifications){ notification_payload = '1'; if(context->bridge->notification_topic){ if(_mosquitto_send_real_publish(context, _mosquitto_mid_generate(context), context->bridge->notification_topic, 1, ¬ification_payload, 1, true, 0)){ return 1; } mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); }else{ notification_topic_len = strlen(context->id)+strlen("$SYS/broker/connection//state"); notification_topic = _mosquitto_malloc(sizeof(char)*(notification_topic_len+1)); if(!notification_topic) return MOSQ_ERR_NOMEM; snprintf(notification_topic, notification_topic_len+1, "$SYS/broker/connection/%s/state", context->id); notification_payload = '1'; if(_mosquitto_send_real_publish(context, _mosquitto_mid_generate(context), notification_topic, 1, ¬ification_payload, 1, true, 0)){ _mosquitto_free(notification_topic); return 1; } mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); _mosquitto_free(notification_topic); } }// end of bridge notifications // broker之间的订阅处理机制,画个图可能好理解点 for(i=0; i<context->bridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_in || context->bridge->topics[i].direction == bd_both){ if(_mosquitto_send_subscribe(context, NULL, false, context->bridge->topics[i].remote_topic, context->bridge->topics[i].qos)){ return 1; } }else{ if(_mosquitto_send_unsubscribe(context, NULL, false, context->bridge->topics[i].remote_topic)){ /* direction = inwards only. This means we should not be subscribed * to the topic. It is possible that we used to be subscribed to * this topic so unsubscribe. */ return 1; } } } } // 原来更新的是客户端的额状态 context->state = mosq_cs_connected; return MOSQ_ERR_SUCCESS; // 连接错误,版本问题 case CONNACK_REFUSED_PROTOCOL_VERSION: if(context->bridge){ context->bridge->try_private_accepted = false; } _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: unacceptable protocol version"); return 1; // case CONNACK_REFUSED_IDENTIFIER_REJECTED: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: identifier rejected"); return 1; // case CONNACK_REFUSED_SERVER_UNAVAILABLE: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: broker unavailable"); return 1; // case CONNACK_REFUSED_BAD_USERNAME_PASSWORD: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: broker unavailable"); return 1; // case CONNACK_REFUSED_NOT_AUTHORIZED: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: not authorised"); return 1; // default: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: unknown reason"); return 1; } return 1; }
static int _subs_process(struct mosquitto_db *db, struct _mosquitto_subhier *hier, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored, bool set_retain) { int rc = 0; int rc2; int client_qos, msg_qos; uint16_t mid; struct _mosquitto_subleaf *leaf; bool client_retain; leaf = hier->subs; if(retain && set_retain){ #ifdef WITH_PERSISTENCE if(strncmp(topic, "$SYS", 4)){ /* Retained messages count as a persistence change, but only if * they aren't for $SYS. */ db->persistence_changes++; } #endif if(hier->retained){ hier->retained->ref_count--; /* FIXME - it would be nice to be able to remove the message from the store at this point if ref_count == 0 */ db->retained_count--; } if(stored->msg.payloadlen){ hier->retained = stored; hier->retained->ref_count++; db->retained_count++; }else{ hier->retained = NULL; } } while(source_id && leaf){ if(leaf->context->is_bridge && !strcmp(leaf->context->id, source_id)){ leaf = leaf->next; continue; } /* Check for ACL topic access. */ rc2 = mosquitto_acl_check(db, leaf->context, topic, MOSQ_ACL_READ); if(rc2 == MOSQ_ERR_ACL_DENIED){ leaf = leaf->next; continue; }else if(rc2 == MOSQ_ERR_SUCCESS){ client_qos = leaf->qos; if(db->config->upgrade_outgoing_qos){ msg_qos = client_qos; }else{ if(qos > client_qos){ msg_qos = client_qos; }else{ msg_qos = qos; } } if(msg_qos){ mid = _mosquitto_mid_generate(leaf->context); }else{ mid = 0; } if(leaf->context->is_bridge){ /* If we know the client is a bridge then we should set retain * even if the message is fresh. If we don't do this, retained * messages won't be propagated. */ client_retain = retain; }else{ /* Client is not a bridge and this isn't a stale message so * retain should be false. */ client_retain = false; } if(mqtt3_db_message_insert(db, leaf->context, mid, mosq_md_out, msg_qos, client_retain, stored) == 1) rc = 1; }else{ return 1; /* Application error */ } leaf = leaf->next; } return rc; }