int bridge__connect(struct mosquitto_db *db, struct mosquitto *context) { int rc, rc2; 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; bridge__packet_cleanup(context); db__message_reconnect_reset(db, context); if(context->clean_session){ 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. */ sub__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){ log__printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); if(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'; db__messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } if (!context->bridge->notifications_local_only) { notification_payload = '0'; rc = 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'; db__messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } if (!context->bridge->notifications_local_only) { notification_payload = '0'; rc = will__set(context, notification_topic, 1, ¬ification_payload, 1, true); mosquitto__free(notification_topic); if(rc != MOSQ_ERR_SUCCESS){ return rc; } } } } 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 = net__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){ net__socket_close(db, context); return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ log__printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ log__printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } return rc; }else if(rc == MOSQ_ERR_CONN_PENDING){ context->state = mosq_cs_connect_pending; } HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(context->sock), context); rc2 = send__connect(context, context->keepalive, context->clean_session); if(rc2 == MOSQ_ERR_SUCCESS){ return rc; }else if(rc2 == MOSQ_ERR_ERRNO && errno == ENOTCONN){ return MOSQ_ERR_SUCCESS; }else{ if(rc2 == MOSQ_ERR_TLS){ return rc2; /* Error already printed */ }else if(rc2 == MOSQ_ERR_ERRNO){ log__printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc2 == MOSQ_ERR_EAI){ log__printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } net__socket_close(db, context); return rc2; } }
int log__vprintf(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); db__messages_easy_queue(&int_db, NULL, topic, 2, strlen(st), st, 0); mosquitto__free(st); }else{ db__messages_easy_queue(&int_db, NULL, topic, 2, strlen(s), s, 0); } } mosquitto__free(s); } return MOSQ_ERR_SUCCESS; }