int mosquitto_main_loop(struct mosquitto_db *db, int *listensock, int listensock_count, int listener_max) { time_t start_time = time(NULL); time_t last_backup = time(NULL); time_t last_store_clean = time(NULL); time_t now; int fdcount; #ifndef WIN32 sigset_t sigblock, origsig; #endif int i; struct pollfd *pollfds = NULL; int pollfd_count = 0; int pollfd_index; #ifndef WIN32 sigemptyset(&sigblock); sigaddset(&sigblock, SIGINT); #endif while(run){ mqtt3_db_sys_update(db, db->config->sys_interval, start_time); if(listensock_count + db->context_count > pollfd_count){ pollfd_count = listensock_count + db->context_count; pollfds = _mosquitto_realloc(pollfds, sizeof(struct pollfd)*pollfd_count); if(!pollfds){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } } memset(pollfds, -1, sizeof(struct pollfd)*pollfd_count); pollfd_index = 0; for(i=0; i<listensock_count; i++){ pollfds[pollfd_index].fd = listensock[i]; pollfds[pollfd_index].events = POLLIN; pollfds[pollfd_index].revents = 0; pollfd_index++; } now = time(NULL); for(i=0; i<db->context_count; i++){ if(db->contexts[i]){ db->contexts[i]->pollfd_index = -1; if(db->contexts[i]->sock != INVALID_SOCKET){ #ifdef WITH_BRIDGE if(db->contexts[i]->bridge){ _mosquitto_check_keepalive(db->contexts[i]); } #endif /* Local bridges never time out in this fashion. */ if(!(db->contexts[i]->keepalive) || db->contexts[i]->bridge || now - db->contexts[i]->last_msg_in < (time_t)(db->contexts[i]->keepalive)*3/2){ if(mqtt3_db_message_write(db->contexts[i]) == MOSQ_ERR_SUCCESS){ pollfds[pollfd_index].fd = db->contexts[i]->sock; pollfds[pollfd_index].events = POLLIN | POLLRDHUP; pollfds[pollfd_index].revents = 0; if(db->contexts[i]->out_packet){ pollfds[pollfd_index].events |= POLLOUT; } db->contexts[i]->pollfd_index = pollfd_index; pollfd_index++; }else{ mqtt3_context_disconnect(db, db->contexts[i]); } }else{ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", db->contexts[i]->id); } /* Client has exceeded keepalive*1.5 */ mqtt3_context_disconnect(db, db->contexts[i]); } }else{ #ifdef WITH_BRIDGE if(db->contexts[i]->bridge){ /* Want to try to restart the bridge connection */ if(!db->contexts[i]->bridge->restart_t){ db->contexts[i]->bridge->restart_t = time(NULL)+db->contexts[i]->bridge->restart_timeout; }else{ if(db->contexts[i]->bridge->start_type == bst_automatic && time(NULL) > db->contexts[i]->bridge->restart_t){ db->contexts[i]->bridge->restart_t = 0; if(mqtt3_bridge_connect(db, db->contexts[i]) == MOSQ_ERR_SUCCESS){ pollfds[pollfd_index].fd = db->contexts[i]->sock; pollfds[pollfd_index].events = POLLIN | POLLRDHUP; pollfds[pollfd_index].revents = 0; if(db->contexts[i]->out_packet){ pollfds[pollfd_index].events |= POLLOUT; } db->contexts[i]->pollfd_index = pollfd_index; pollfd_index++; }else{ /* Retry later. */ db->contexts[i]->bridge->restart_t = time(NULL)+db->contexts[i]->bridge->restart_timeout; } } } }else{ #endif if(db->contexts[i]->clean_session == true){ mqtt3_context_cleanup(db, db->contexts[i], true); db->contexts[i] = NULL; }else if(db->config->persistent_client_expiration > 0){ /* This is a persistent client, check to see if the * last time it connected was longer than * persistent_client_expiration seconds ago. If so, * expire it and clean up. */ if(time(NULL) > db->contexts[i]->disconnect_t+db->config->persistent_client_expiration){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Expiring persistent client %s due to timeout.", db->contexts[i]->id); g_clients_expired++; db->contexts[i]->clean_session = true; mqtt3_context_cleanup(db, db->contexts[i], true); db->contexts[i] = NULL; } } #ifdef WITH_BRIDGE } #endif } } } mqtt3_db_message_timeout_check(db, db->config->retry_interval); #ifndef WIN32 sigprocmask(SIG_SETMASK, &sigblock, &origsig); fdcount = poll(pollfds, pollfd_index, 100); sigprocmask(SIG_SETMASK, &origsig, NULL); #else fdcount = WSAPoll(pollfds, pollfd_index, 100); #endif if(fdcount == -1){ loop_handle_errors(db, pollfds); }else{ loop_handle_reads_writes(db, pollfds); for(i=0; i<listensock_count; i++){ if(pollfds[i].revents & (POLLIN | POLLPRI)){ while(mqtt3_socket_accept(db, listensock[i]) != -1){ } } } } #ifdef WITH_PERSISTENCE if(db->config->persistence && db->config->autosave_interval){ if(db->config->autosave_on_changes){ if(db->persistence_changes > db->config->autosave_interval){ mqtt3_db_backup(db, false, false); db->persistence_changes = 0; } }else{ if(last_backup + db->config->autosave_interval < now){ mqtt3_db_backup(db, false, false); last_backup = time(NULL); } } } #endif if(!db->config->store_clean_interval || last_store_clean + db->config->store_clean_interval < now){ mqtt3_db_store_clean(db); last_store_clean = time(NULL); } #ifdef WITH_PERSISTENCE if(flag_db_backup){ mqtt3_db_backup(db, false, false); flag_db_backup = false; } #endif if(flag_reload){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Reloading config."); mqtt3_config_read(db->config, true); mosquitto_security_cleanup(db, true); mosquitto_security_init(db, true); mosquitto_security_apply(db); mqtt3_log_init(db->config->log_type, db->config->log_dest); flag_reload = false; } if(flag_tree_print){ mqtt3_sub_tree_print(&db->subs, 0); flag_tree_print = false; } } if(pollfds) _mosquitto_free(pollfds); return MOSQ_ERR_SUCCESS; }
int mosquitto_main_loop(struct mosquitto_db *db, int *listensock, int listensock_count, int listener_max) { time_t start_time = time(NULL); time_t last_backup = time(NULL); time_t last_store_clean = time(NULL); time_t now; sigset_t sigblock, origsig; int i, s; /* temp variables */ struct epoll_event* events = NULL; int epollfd_count = 0; int epollfd_index; int efd; /* epoll fd */ while (run) { mqtt3_db_sys_update(db, db->config->sys_interval, start_time); events = init_events(events, listensock_count, db->context_count, &epollfd_count); if (!events) { _mosquitto_log_printf (NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } memset(events, -1, sizeof(struct epoll_event) * epollfd_count); epollfd_index = 0; efd = create_event(events, listensock, listensock_count, &epollfd_index); now = time (NULL); reg_context_events(db, events, &epollfd_index, efd, now); mqtt3_db_message_timeout_check(db, db->config->retry_interval); sigprocmask(SIG_SETMASK, &sigblock, &origsig); s = epoll_wait(efd, events, 64, -1); if (s == -1) { printf("errno value: %d, it means: %s", errno, strerror(errno)); loop_handle_errors(db, events, efd); } if (s == -1) { printf("errno value: %d, it means: %s", errno, strerror(errno)); loop_handle_errors(db, events, efd); } else{ loop_handle_reads_writes(db, events, efd); for(i=0; i<listensock_count; i++){ if(events[i].events & (EPOLLIN | EPOLLPRI)){ while((s = mqtt3_socket_accept(db, listensock[i], &events[i], efd)) != -1){ } } } } sigprocmask(SIG_SETMASK, &origsig, NULL); #ifdef WITH_PERSISTENCE if(db->config->persistence && db->config->autosave_interval){ if(db->config->autosave_on_changes){ if(db->persistence_changes > db->config->autosave_interval){ mqtt3_db_backup(db, false, false); db->persistence_changes = 0; } }else{ if(last_backup + db->config->autosave_interval < now){ mqtt3_db_backup(db, false, false); last_backup = time(NULL); } } } #endif if(!db->config->store_clean_interval || last_store_clean + db->config->store_clean_interval < now){ mqtt3_db_store_clean(db); last_store_clean = time(NULL); } #ifdef WITH_PERSISTENCE if(flag_db_backup){ mqtt3_db_backup(db, false, false); flag_db_backup = false; } #endif if(flag_reload){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Reloading config."); mqtt3_config_read(db->config, true); mosquitto_security_cleanup(db, true); mosquitto_security_init(db, true); mosquitto_security_apply(db); mqtt3_log_init(db->config->log_type, db->config->log_dest); flag_reload = false; } if(flag_tree_print){ mqtt3_sub_tree_print(&db->subs, 0); flag_tree_print = false; } } if(events) _mosquitto_free(events); return MOSQ_ERR_SUCCESS; }
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; }