static void _sys_update_memory(struct mosquitto_db *db, char *buf) { static unsigned long current_heap = -1; static unsigned long max_heap = -1; unsigned long value_ul; value_ul = _mosquitto_memory_used(); if(current_heap != value_ul){ current_heap = value_ul; snprintf(buf, BUFLEN, "%lu", current_heap); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/heap/current size", 2, strlen(buf), buf, 1); } value_ul =_mosquitto_max_memory_used(); if(max_heap != value_ul){ max_heap = value_ul; snprintf(buf, BUFLEN, "%lu", max_heap); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/heap/maximum size", 2, strlen(buf), buf, 1); } }
static void calc_load(struct mosquitto_db *db, char *buf, const char *topic, double exponent, double interval, double *current) { double new_value; new_value = interval + exponent*((*current) - interval); if(fabs(new_value - (*current)) >= 0.01){ snprintf(buf, BUFLEN, "%.2f", new_value); mqtt3_db_messages_easy_queue(db, NULL, topic, 2, strlen(buf), buf, 1); } (*current) = new_value; }
static void _sys_update_clients(struct mosquitto_db *db, char *buf) { static unsigned int client_count = -1; static int clients_expired = -1; static unsigned int client_max = -1; static unsigned int inactive_count = -1; static unsigned int active_count = -1; unsigned int value; unsigned int inactive; unsigned int active; if(!mqtt3_db_client_count(db, &value, &inactive)){ if(client_count != value){ client_count = value; snprintf(buf, BUFLEN, "%d", client_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/total", 2, strlen(buf), buf, 1); } if(inactive_count != inactive){ inactive_count = inactive; snprintf(buf, BUFLEN, "%d", inactive_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/inactive", 2, strlen(buf), buf, 1); } active = client_count - inactive; if(active_count != active){ active_count = active; snprintf(buf, BUFLEN, "%d", active_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/active", 2, strlen(buf), buf, 1); } if(value != client_max){ client_max = value; snprintf(buf, BUFLEN, "%d", client_max); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/maximum", 2, strlen(buf), buf, 1); } } if(g_clients_expired != clients_expired){ clients_expired = g_clients_expired; snprintf(buf, BUFLEN, "%d", clients_expired); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/expired", 2, strlen(buf), buf, 1); } }
void mqtt3_context_disconnect(struct mosquitto_db *db, struct mosquitto *ctxt) { if(ctxt->state != mosq_cs_disconnecting && ctxt->will){ if(mosquitto_acl_check(db, ctxt, ctxt->will->topic, MOSQ_ACL_WRITE) == MOSQ_ERR_SUCCESS){ /* Unexpected disconnect, queue the client will. */ mqtt3_db_messages_easy_queue(db, ctxt, ctxt->will->topic, ctxt->will->qos, ctxt->will->payloadlen, ctxt->will->payload, ctxt->will->retain); } } if(ctxt->will){ if(ctxt->will->topic) _mosquitto_free(ctxt->will->topic); if(ctxt->will->payload) _mosquitto_free(ctxt->will->payload); _mosquitto_free(ctxt->will); ctxt->will = NULL; } ctxt->disconnect_t = time(NULL); _mosquitto_socket_close(db, ctxt); }
void mqtt3_context_disconnect(struct mosquitto_db *db, struct mosquitto *ctxt) { if(ctxt->state != mosq_cs_disconnecting && ctxt->will){ /* Unexpected disconnect, queue the client will. */ mqtt3_db_messages_easy_queue(db, ctxt, ctxt->will->topic, ctxt->will->qos, ctxt->will->payloadlen, ctxt->will->payload, ctxt->will->retain); } if(ctxt->will){ if(ctxt->will->topic) _mosquitto_free(ctxt->will->topic); if(ctxt->will->payload) _mosquitto_free(ctxt->will->payload); _mosquitto_free(ctxt->will); ctxt->will = NULL; } if(ctxt->listener){ ctxt->listener->client_count--; assert(ctxt->listener->client_count >= 0); ctxt->listener = NULL; } ctxt->disconnect_t = mosquitto_time(); _mosquitto_socket_close(ctxt); }
static void _sys_update_clients(struct mosquitto_db *db, char *buf) { static unsigned int client_count = -1; static int clients_expired = -1; static unsigned int client_max = -1; static unsigned int disconnected_count = -1; static unsigned int connected_count = -1; if(client_count != db->connected_count + db->disconnected_count){ client_count = db->connected_count + db->disconnected_count; snprintf(buf, BUFLEN, "%d", client_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/total", 2, strlen(buf), buf, 1); if(client_count > client_max){ client_max = client_count; snprintf(buf, BUFLEN, "%d", client_max); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/maximum", 2, strlen(buf), buf, 1); } } if(disconnected_count != db->disconnected_count){ disconnected_count = db->disconnected_count; snprintf(buf, BUFLEN, "%d", disconnected_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/inactive", 2, strlen(buf), buf, 1); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/disconnected", 2, strlen(buf), buf, 1); } if(connected_count != db->connected_count){ connected_count = db->connected_count; snprintf(buf, BUFLEN, "%d", connected_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/active", 2, strlen(buf), buf, 1); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/connected", 2, strlen(buf), buf, 1); } if(g_clients_expired != clients_expired){ clients_expired = g_clients_expired; snprintf(buf, BUFLEN, "%d", clients_expired); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/expired", 2, strlen(buf), buf, 1); } }
/* Send messages for the $SYS hierarchy if the last update is longer than * 'interval' seconds ago. * 'interval' is the amount of seconds between updates. If 0, then no periodic * messages are sent for the $SYS hierarchy. * 'start_time' is the result of time() that the broker was started at. */ void mqtt3_db_sys_update(struct mosquitto_db *db, int interval, time_t start_time) { static time_t last_update = 0; time_t now; time_t uptime; char buf[BUFLEN]; static int msg_store_count = -1; static unsigned long msgs_received = -1; static unsigned long msgs_sent = -1; static unsigned long publish_dropped = -1; static unsigned long pub_msgs_received = -1; static unsigned long pub_msgs_sent = -1; static unsigned long long bytes_received = -1; static unsigned long long bytes_sent = -1; static unsigned long long pub_bytes_received = -1; static unsigned long long pub_bytes_sent = -1; static int subscription_count = -1; static int retained_count = -1; static double msgs_received_load1 = 0; static double msgs_received_load5 = 0; static double msgs_received_load15 = 0; static double msgs_sent_load1 = 0; static double msgs_sent_load5 = 0; static double msgs_sent_load15 = 0; static double publish_dropped_load1 = 0; static double publish_dropped_load5 = 0; static double publish_dropped_load15 = 0; double msgs_received_interval, msgs_sent_interval, publish_dropped_interval; static double publish_received_load1 = 0; static double publish_received_load5 = 0; static double publish_received_load15 = 0; static double publish_sent_load1 = 0; static double publish_sent_load5 = 0; static double publish_sent_load15 = 0; double publish_received_interval, publish_sent_interval; static double bytes_received_load1 = 0; static double bytes_received_load5 = 0; static double bytes_received_load15 = 0; static double bytes_sent_load1 = 0; static double bytes_sent_load5 = 0; static double bytes_sent_load15 = 0; double bytes_received_interval, bytes_sent_interval; static double socket_load1 = 0; static double socket_load5 = 0; static double socket_load15 = 0; double socket_interval; static double connection_load1 = 0; static double connection_load5 = 0; static double connection_load15 = 0; double connection_interval; double exponent; double i_mult; now = mosquitto_time(); if(interval && now - interval > last_update){ uptime = now - start_time; snprintf(buf, BUFLEN, "%d seconds", (int)uptime); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/uptime", 2, strlen(buf), buf, 1); _sys_update_clients(db, buf); if(last_update > 0){ i_mult = 60.0/(double)(now-last_update); msgs_received_interval = (g_msgs_received - msgs_received)*i_mult; msgs_sent_interval = (g_msgs_sent - msgs_sent)*i_mult; publish_dropped_interval = (g_msgs_dropped - publish_dropped)*i_mult; publish_received_interval = (g_pub_msgs_received - pub_msgs_received)*i_mult; publish_sent_interval = (g_pub_msgs_sent - pub_msgs_sent)*i_mult; bytes_received_interval = (g_bytes_received - bytes_received)*i_mult; bytes_sent_interval = (g_bytes_sent - bytes_sent)*i_mult; socket_interval = g_socket_connections*i_mult; g_socket_connections = 0; connection_interval = g_connection_count*i_mult; g_connection_count = 0; /* 1 minute load */ exponent = exp(-1.0*(now-last_update)/60.0); calc_load(db, buf, "$SYS/broker/load/messages/received/1min", exponent, msgs_received_interval, &msgs_received_load1); calc_load(db, buf, "$SYS/broker/load/messages/sent/1min", exponent, msgs_sent_interval, &msgs_sent_load1); calc_load(db, buf, "$SYS/broker/load/publish/dropped/1min", exponent, publish_dropped_interval, &publish_dropped_load1); calc_load(db, buf, "$SYS/broker/load/publish/received/1min", exponent, publish_received_interval, &publish_received_load1); calc_load(db, buf, "$SYS/broker/load/publish/sent/1min", exponent, publish_sent_interval, &publish_sent_load1); calc_load(db, buf, "$SYS/broker/load/bytes/received/1min", exponent, bytes_received_interval, &bytes_received_load1); calc_load(db, buf, "$SYS/broker/load/bytes/sent/1min", exponent, bytes_sent_interval, &bytes_sent_load1); calc_load(db, buf, "$SYS/broker/load/sockets/1min", exponent, socket_interval, &socket_load1); calc_load(db, buf, "$SYS/broker/load/connections/1min", exponent, connection_interval, &connection_load1); /* 5 minute load */ exponent = exp(-1.0*(now-last_update)/300.0); calc_load(db, buf, "$SYS/broker/load/messages/received/5min", exponent, msgs_received_interval, &msgs_received_load5); calc_load(db, buf, "$SYS/broker/load/messages/sent/5min", exponent, msgs_sent_interval, &msgs_sent_load5); calc_load(db, buf, "$SYS/broker/load/publish/dropped/5min", exponent, publish_dropped_interval, &publish_dropped_load5); calc_load(db, buf, "$SYS/broker/load/publish/received/5min", exponent, publish_received_interval, &publish_received_load5); calc_load(db, buf, "$SYS/broker/load/publish/sent/5min", exponent, publish_sent_interval, &publish_sent_load5); calc_load(db, buf, "$SYS/broker/load/bytes/received/5min", exponent, bytes_received_interval, &bytes_received_load5); calc_load(db, buf, "$SYS/broker/load/bytes/sent/5min", exponent, bytes_sent_interval, &bytes_sent_load5); calc_load(db, buf, "$SYS/broker/load/sockets/5min", exponent, socket_interval, &socket_load5); calc_load(db, buf, "$SYS/broker/load/connections/5min", exponent, connection_interval, &connection_load5); /* 15 minute load */ exponent = exp(-1.0*(now-last_update)/900.0); calc_load(db, buf, "$SYS/broker/load/messages/received/15min", exponent, msgs_received_interval, &msgs_received_load15); calc_load(db, buf, "$SYS/broker/load/messages/sent/15min", exponent, msgs_sent_interval, &msgs_sent_load15); calc_load(db, buf, "$SYS/broker/load/publish/dropped/15min", exponent, publish_dropped_interval, &publish_dropped_load15); calc_load(db, buf, "$SYS/broker/load/publish/received/15min", exponent, publish_received_interval, &publish_received_load15); calc_load(db, buf, "$SYS/broker/load/publish/sent/15min", exponent, publish_sent_interval, &publish_sent_load15); calc_load(db, buf, "$SYS/broker/load/bytes/received/15min", exponent, bytes_received_interval, &bytes_received_load15); calc_load(db, buf, "$SYS/broker/load/bytes/sent/15min", exponent, bytes_sent_interval, &bytes_sent_load15); calc_load(db, buf, "$SYS/broker/load/sockets/15min", exponent, socket_interval, &socket_load15); calc_load(db, buf, "$SYS/broker/load/connections/15min", exponent, connection_interval, &connection_load15); } if(db->msg_store_count != msg_store_count){ msg_store_count = db->msg_store_count; snprintf(buf, BUFLEN, "%d", msg_store_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/stored", 2, strlen(buf), buf, 1); } if(db->subscription_count != subscription_count){ subscription_count = db->subscription_count; snprintf(buf, BUFLEN, "%d", subscription_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/subscriptions/count", 2, strlen(buf), buf, 1); } if(db->retained_count != retained_count){ retained_count = db->retained_count; snprintf(buf, BUFLEN, "%d", retained_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/retained messages/count", 2, strlen(buf), buf, 1); } #ifdef REAL_WITH_MEMORY_TRACKING _sys_update_memory(db, buf); #endif if(msgs_received != g_msgs_received){ msgs_received = g_msgs_received; snprintf(buf, BUFLEN, "%lu", msgs_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/received", 2, strlen(buf), buf, 1); } if(msgs_sent != g_msgs_sent){ msgs_sent = g_msgs_sent; snprintf(buf, BUFLEN, "%lu", msgs_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/sent", 2, strlen(buf), buf, 1); } if(publish_dropped != g_msgs_dropped){ publish_dropped = g_msgs_dropped; snprintf(buf, BUFLEN, "%lu", publish_dropped); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/publish/messages/dropped", 2, strlen(buf), buf, 1); } if(pub_msgs_received != g_pub_msgs_received){ pub_msgs_received = g_pub_msgs_received; snprintf(buf, BUFLEN, "%lu", pub_msgs_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/publish/messages/received", 2, strlen(buf), buf, 1); } if(pub_msgs_sent != g_pub_msgs_sent){ pub_msgs_sent = g_pub_msgs_sent; snprintf(buf, BUFLEN, "%lu", pub_msgs_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/publish/messages/sent", 2, strlen(buf), buf, 1); } if(bytes_received != g_bytes_received){ bytes_received = g_bytes_received; snprintf(buf, BUFLEN, "%llu", bytes_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/received", 2, strlen(buf), buf, 1); } if(bytes_sent != g_bytes_sent){ bytes_sent = g_bytes_sent; snprintf(buf, BUFLEN, "%llu", bytes_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/sent", 2, strlen(buf), buf, 1); } if(pub_bytes_received != g_pub_bytes_received){ pub_bytes_received = g_pub_bytes_received; snprintf(buf, BUFLEN, "%llu", pub_bytes_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/publish/bytes/received", 2, strlen(buf), buf, 1); } if(pub_bytes_sent != g_pub_bytes_sent){ pub_bytes_sent = g_pub_bytes_sent; snprintf(buf, BUFLEN, "%llu", pub_bytes_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/publish/bytes/sent", 2, strlen(buf), buf, 1); } last_update = mosquitto_time(); } // 大于interval了,就更新订阅信息 }
int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) { int rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload; if(!context || !context->bridge) return MOSQ_ERR_INVAL; context->state = mosq_cs_new; context->sock = INVALID_SOCKET; context->last_msg_in = mosquitto_time(); context->next_msg_out = mosquitto_time() + context->bridge->keepalive; context->keepalive = context->bridge->keepalive; context->clean_session = context->bridge->clean_session; context->in_packet.payload = NULL; context->ping_t = 0; context->bridge->lazy_reconnect = false; mqtt3_bridge_packet_cleanup(context); mqtt3_db_message_reconnect_reset(db, context); if(context->clean_session){ mqtt3_db_messages_delete(db, context); } /* Delete all local subscriptions even for clean_session==false. We don't * remove any messages and the next loop carries out the resubscription * anyway. This means any unwanted subs will be removed. */ mqtt3_subs_clean_session(db, context); for(i=0; i<context->bridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1; } } if(context->bridge->notifications){ if(context->bridge->notification_topic){ if(!context->bridge->initial_notification_done){ notification_payload = '0'; mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } notification_payload = '0'; rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ return rc; } }else{ notification_topic_len = strlen(context->bridge->remote_clientid)+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->bridge->remote_clientid); if(!context->bridge->initial_notification_done){ notification_payload = '0'; mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } notification_payload = '0'; rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true); _mosquitto_free(notification_topic); if(rc != MOSQ_ERR_SUCCESS){ return rc; } } } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); if(rc > 0 ){ if(rc == MOSQ_ERR_TLS){ _mosquitto_socket_close(db, context); return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } return rc; } HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(context->sock), context); if(rc == MOSQ_ERR_CONN_PENDING){ context->state = mosq_cs_connect_pending; } rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session); if(rc == MOSQ_ERR_SUCCESS){ return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ return MOSQ_ERR_SUCCESS; }else{ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } _mosquitto_socket_close(db, context); return rc; } }
int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) { int rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload; if(!context || !context->bridge) return MOSQ_ERR_INVAL; context->state = mosq_cs_new; context->sock = -1; context->last_msg_in = mosquitto_time(); context->last_msg_out = mosquitto_time(); context->keepalive = context->bridge->keepalive; context->clean_session = context->bridge->clean_session; context->in_packet.payload = NULL; context->ping_t = 0; context->bridge->lazy_reconnect = false; mqtt3_bridge_packet_cleanup(context); mqtt3_db_message_reconnect_reset(context); if(context->clean_session){ mqtt3_db_messages_delete(context); } rc = mosquitto_unpwd_check(db, context->bridge->local_username, context->bridge->local_password); switch(rc){ case MOSQ_ERR_SUCCESS: break; case MOSQ_ERR_AUTH: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Bridge %s failed authentication on local broker.", context->id); return rc; case MOSQ_ERR_UNKNOWN: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Bridge %s returned application error in authorisation.", context->id); return rc; default: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Unknown error in authentication for bridge %s.", context->id); return rc; } /* Delete all local subscriptions even for clean_session==false. We don't * remove any messages and the next loop carries out the resubscription * anyway. This means any unwanted subs will be removed. */ mqtt3_subs_clean_session(db, context, &db->subs); for(i=0; i<context->bridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1; } } if(context->bridge->notifications){ notification_payload = '0'; if(context->bridge->notification_topic){ mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ return rc; } }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); mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_free(notification_topic); return rc; } _mosquitto_free(notification_topic); } } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, true); if(rc != MOSQ_ERR_SUCCESS){ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } return rc; } rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session); if(rc == MOSQ_ERR_SUCCESS){ return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ return MOSQ_ERR_SUCCESS; }else{ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } _mosquitto_socket_close(context); return rc; } }
/* 整个.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; }
int main(int argc, char *argv[]) { int *listensock = NULL; int listensock_count = 0; int listensock_index = 0; struct mqtt3_config config; char buf[1024]; int i, j; FILE *pid; int listener_max; int rc; char err[256]; #ifdef WIN32 SYSTEMTIME st; #else struct timeval tv; #endif #if defined(WIN32) || defined(__CYGWIN__) if(argc == 2){ if(!strcmp(argv[1], "run")){ service_run(); return 0; }else if(!strcmp(argv[1], "install")){ service_install(); return 0; }else if(!strcmp(argv[1], "uninstall")){ service_uninstall(); return 0; } } #endif #ifdef WIN32 GetSystemTime(&st); srand(st.wSecond + st.wMilliseconds); #else gettimeofday(&tv, NULL); srand(tv.tv_sec + tv.tv_usec); #endif memset(&int_db, 0, sizeof(struct mosquitto_db)); _mosquitto_net_init(); mqtt3_config_init(&config); rc = mqtt3_config_parse_args(&config, argc, argv); if(rc != MOSQ_ERR_SUCCESS) return rc; int_db.config = &config; if(config.daemon){ #ifndef WIN32 switch(fork()){ case 0: break; case -1: strerror_r(errno, err, 256); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in fork: %s", err); return 1; default: return MOSQ_ERR_SUCCESS; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows."); #endif } if(config.daemon && config.pid_file){ pid = _mosquitto_fopen(config.pid_file, "wt"); if(pid){ fprintf(pid, "%d", getpid()); fclose(pid); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to write pid file."); return 1; } } rc = drop_privileges(&config); if(rc != MOSQ_ERR_SUCCESS) return rc; rc = mqtt3_db_open(&config, &int_db); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Couldn't open database."); return rc; } /* Initialise logging only after initialising the database in case we're * logging to topics */ mqtt3_log_init(config.log_type, config.log_dest); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s (build date %s) starting", VERSION, TIMESTAMP); if(config.config_file){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Config loaded from %s.", config.config_file); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Using default config."); } rc = mosquitto_security_module_init(&int_db); if(rc) return rc; rc = mosquitto_security_init(&int_db, false); if(rc) return rc; #ifdef WITH_SYS_TREE if(config.sys_interval > 0){ /* Set static $SYS messages */ snprintf(buf, 1024, "mosquitto version %s", VERSION); mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/version", 2, strlen(buf), buf, 1); snprintf(buf, 1024, "%s", TIMESTAMP); mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/timestamp", 2, strlen(buf), buf, 1); #ifdef CHANGESET snprintf(buf, 1024, "%s", CHANGESET); mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/changeset", 2, strlen(buf), buf, 1); #endif } #endif listener_max = -1; listensock_index = 0; for(i=0; i<config.listener_count; i++){ if(mqtt3_socket_listen(&config.listeners[i])){ _mosquitto_free(int_db.contexts); mqtt3_db_close(&int_db); if(config.pid_file){ remove(config.pid_file); } return 1; } listensock_count += config.listeners[i].sock_count; listensock = _mosquitto_realloc(listensock, sizeof(int)*listensock_count); if(!listensock){ _mosquitto_free(int_db.contexts); mqtt3_db_close(&int_db); if(config.pid_file){ remove(config.pid_file); } return 1; } for(j=0; j<config.listeners[i].sock_count; j++){ if(config.listeners[i].socks[j] == INVALID_SOCKET){ _mosquitto_free(int_db.contexts); mqtt3_db_close(&int_db); if(config.pid_file){ remove(config.pid_file); } return 1; } listensock[listensock_index] = config.listeners[i].socks[j]; if(listensock[listensock_index] > listener_max){ listener_max = listensock[listensock_index]; } listensock_index++; } } signal(SIGINT, handle_sigint); signal(SIGTERM, handle_sigint); #ifdef SIGHUP signal(SIGHUP, handle_sighup); #endif #ifndef WIN32 signal(SIGUSR1, handle_sigusr1); signal(SIGUSR2, handle_sigusr2); signal(SIGPIPE, SIG_IGN); #endif #ifdef WITH_BRIDGE for(i=0; i<config.bridge_count; i++){ if(mqtt3_bridge_new(&int_db, &(config.bridges[i]))){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Unable to connect to bridge %s.", config.bridges[i].name); } } #endif run = 1; rc = mosquitto_main_loop(&int_db, listensock, listensock_count, listener_max); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s terminating", VERSION); mqtt3_log_close(); #ifdef WITH_PERSISTENCE if(config.persistence){ mqtt3_db_backup(&int_db, true, true); } #endif for(i=0; i<int_db.context_count; i++){ if(int_db.contexts[i]){ mqtt3_context_cleanup(&int_db, int_db.contexts[i], true); } } _mosquitto_free(int_db.contexts); int_db.contexts = NULL; mqtt3_db_close(&int_db); if(listensock){ for(i=0; i<listensock_count; i++){ if(listensock[i] != INVALID_SOCKET){ #ifndef WIN32 close(listensock[i]); #else closesocket(listensock[i]); #endif } } _mosquitto_free(listensock); } mosquitto_security_module_cleanup(&int_db); if(config.pid_file){ remove(config.pid_file); } _mosquitto_net_cleanup(); mqtt3_config_cleanup(int_db.config); return rc; }
int _mosquitto_log_vprintf(struct mosquitto *mosq, int priority, const char *fmt, va_list va) { char *s; char *st; int len; #ifdef WIN32 char *sp; #endif const char *topic; int syslog_priority; time_t now = time(NULL); static time_t last_flush = 0; if((log_priorities & priority) && log_destinations != MQTT3_LOG_NONE){ switch(priority){ case MOSQ_LOG_SUBSCRIBE: topic = "$SYS/broker/log/M/subscribe"; #ifndef WIN32 syslog_priority = LOG_NOTICE; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_UNSUBSCRIBE: topic = "$SYS/broker/log/M/unsubscribe"; #ifndef WIN32 syslog_priority = LOG_NOTICE; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_DEBUG: topic = "$SYS/broker/log/D"; #ifndef WIN32 syslog_priority = LOG_DEBUG; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_ERR: topic = "$SYS/broker/log/E"; #ifndef WIN32 syslog_priority = LOG_ERR; #else syslog_priority = EVENTLOG_ERROR_TYPE; #endif break; case MOSQ_LOG_WARNING: topic = "$SYS/broker/log/W"; #ifndef WIN32 syslog_priority = LOG_WARNING; #else syslog_priority = EVENTLOG_WARNING_TYPE; #endif break; case MOSQ_LOG_NOTICE: topic = "$SYS/broker/log/N"; #ifndef WIN32 syslog_priority = LOG_NOTICE; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_INFO: topic = "$SYS/broker/log/I"; #ifndef WIN32 syslog_priority = LOG_INFO; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; #ifdef WITH_WEBSOCKETS case MOSQ_LOG_WEBSOCKETS: topic = "$SYS/broker/log/WS"; #ifndef WIN32 syslog_priority = LOG_DEBUG; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; #endif default: topic = "$SYS/broker/log/E"; #ifndef WIN32 syslog_priority = LOG_ERR; #else syslog_priority = EVENTLOG_ERROR_TYPE; #endif } len = strlen(fmt) + 500; s = _mosquitto_malloc(len*sizeof(char)); if(!s) return MOSQ_ERR_NOMEM; vsnprintf(s, len, fmt, va); s[len-1] = '\0'; /* Ensure string is null terminated. */ if(log_destinations & MQTT3_LOG_STDOUT){ if(int_db.config && int_db.config->log_timestamp){ fprintf(stdout, "%d: %s\n", (int)now, s); }else{ fprintf(stdout, "%s\n", s); } fflush(stdout); } if(log_destinations & MQTT3_LOG_STDERR){ if(int_db.config && int_db.config->log_timestamp){ fprintf(stderr, "%d: %s\n", (int)now, s); }else{ fprintf(stderr, "%s\n", s); } fflush(stderr); } if(log_destinations & MQTT3_LOG_FILE && int_db.config->log_fptr){ if(int_db.config && int_db.config->log_timestamp){ fprintf(int_db.config->log_fptr, "%d: %s\n", (int)now, s); }else{ fprintf(int_db.config->log_fptr, "%s\n", s); } if(now - last_flush > 1){ fflush(int_db.config->log_fptr); last_flush = now; } } if(log_destinations & MQTT3_LOG_SYSLOG){ #ifndef WIN32 syslog(syslog_priority, "%s", s); #else sp = (char *)s; ReportEvent(syslog_h, syslog_priority, 0, 0, NULL, 1, 0, &sp, NULL); #endif } if(log_destinations & MQTT3_LOG_TOPIC && priority != MOSQ_LOG_DEBUG){ if(int_db.config && int_db.config->log_timestamp){ len += 30; st = _mosquitto_malloc(len*sizeof(char)); if(!st){ _mosquitto_free(s); return MOSQ_ERR_NOMEM; } snprintf(st, len, "%d: %s", (int)now, s); mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(st), st, 0); _mosquitto_free(st); }else{ mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(s), s, 0); } } _mosquitto_free(s); } return MOSQ_ERR_SUCCESS; }