static void create_bridge_events( struct mosquitto_db* db, struct epoll_event* events, int* epollfd_index, int efd, int i) { /* 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){ nonblocking (db->contexts[i]->sock); events[*epollfd_index].data.fd = db->contexts[i]->sock; events[*epollfd_index].events = EPOLLIN | POLLRDHUP; if(db->contexts[i]->out_packet){ events[*epollfd_index].events |= EPOLLOUT; } epoll_ctl (efd, EPOLL_CTL_ADD, db->contexts[i]->sock, &events[*epollfd_index]); db->contexts[i]->pollfd_index = *epollfd_index; *epollfd_index = *epollfd_index + 1; } else { /* Retry later. */ db->contexts[i]->bridge->restart_t = time(NULL)+db->contexts[i]->bridge->restart_timeout; } } } }
int mqtt3_bridge_new(mosquitto_db *db, struct _mqtt3_bridge *bridge) { int i; mqtt3_context *new_context = NULL; mqtt3_context **tmp_contexts; assert(db); assert(bridge); new_context = mqtt3_context_init(-1); if(!new_context){ return MOSQ_ERR_NOMEM; } new_context->bridge = bridge; for(i=0; i<db->context_count; i++){ if(db->contexts[i] == NULL){ db->contexts[i] = new_context; break; } } if(i==db->context_count){ db->context_count++; tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(mqtt3_context*)*db->context_count); if(tmp_contexts){ db->contexts = tmp_contexts; db->contexts[db->context_count-1] = new_context; }else{ return MOSQ_ERR_NOMEM; } } /* FIXME - need to check that this name isn't already in use. */ new_context->core.id = _mosquitto_strdup(bridge->name); if(!new_context->core.id){ return MOSQ_ERR_NOMEM; } new_context->core.username = new_context->bridge->username; new_context->core.password = new_context->bridge->password; return mqtt3_bridge_connect(db, new_context); }
int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) { struct mosquitto *new_context = NULL; struct mosquitto **bridges; char hostname[256]; int len; char *id, *local_id; assert(db); assert(bridge); if(!bridge->remote_clientid){ if(!gethostname(hostname, 256)){ len = strlen(hostname) + strlen(bridge->name) + 2; id = _mosquitto_malloc(len); if(!id){ return MOSQ_ERR_NOMEM; } snprintf(id, len, "%s.%s", hostname, bridge->name); }else{ return 1; } bridge->remote_clientid = id; } if(bridge->local_clientid){ local_id = _mosquitto_strdup(bridge->local_clientid); if(!local_id){ return MOSQ_ERR_NOMEM; } }else{ len = strlen(bridge->remote_clientid) + strlen("local.") + 2; local_id = _mosquitto_malloc(len); if(!local_id){ return MOSQ_ERR_NOMEM; } snprintf(local_id, len, "local.%s", bridge->remote_clientid); bridge->local_clientid = _mosquitto_strdup(local_id); if(!bridge->local_clientid){ _mosquitto_free(local_id); return MOSQ_ERR_NOMEM; } } HASH_FIND(hh_id, db->contexts_by_id, local_id, strlen(local_id), new_context); if(new_context){ /* (possible from persistent db) */ _mosquitto_free(local_id); }else{ /* id wasn't found, so generate a new context */ new_context = mqtt3_context_init(db, -1); if(!new_context){ _mosquitto_free(local_id); return MOSQ_ERR_NOMEM; } new_context->id = local_id; HASH_ADD_KEYPTR(hh_id, db->contexts_by_id, new_context->id, strlen(new_context->id), new_context); } new_context->bridge = bridge; new_context->is_bridge = true; new_context->username = new_context->bridge->remote_username; new_context->password = new_context->bridge->remote_password; #ifdef WITH_TLS new_context->tls_cafile = new_context->bridge->tls_cafile; new_context->tls_capath = new_context->bridge->tls_capath; new_context->tls_certfile = new_context->bridge->tls_certfile; new_context->tls_keyfile = new_context->bridge->tls_keyfile; new_context->tls_cert_reqs = SSL_VERIFY_PEER; new_context->tls_version = new_context->bridge->tls_version; new_context->tls_insecure = new_context->bridge->tls_insecure; #ifdef REAL_WITH_TLS_PSK new_context->tls_psk_identity = new_context->bridge->tls_psk_identity; new_context->tls_psk = new_context->bridge->tls_psk; #endif #endif bridge->try_private_accepted = true; new_context->protocol = bridge->protocol_version; bridges = _mosquitto_realloc(db->bridges, (db->bridge_count+1)*sizeof(struct mosquitto *)); if(bridges){ db->bridges = bridges; db->bridge_count++; db->bridges[db->bridge_count-1] = new_context; }else{ return MOSQ_ERR_NOMEM; } return mqtt3_bridge_connect(db, new_context); }
int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) { int i; struct mosquitto *new_context = NULL; int null_index = -1; struct mosquitto **tmp_contexts; char hostname[256]; int len; char *id; assert(db); assert(bridge); if(bridge->clientid){ id = _mosquitto_strdup(bridge->clientid); }else{ if(!gethostname(hostname, 256)){ len = strlen(hostname) + strlen(bridge->name) + 2; id = _mosquitto_malloc(len); if(!id){ return MOSQ_ERR_NOMEM; } snprintf(id, len, "%s.%s", hostname, bridge->name); }else{ return 1; } } if(!id){ return MOSQ_ERR_NOMEM; } /* Search for existing id (possible from persistent db) and also look for a * gap in the db->contexts[] array in case the id isn't found. */ for(i=0; i<db->context_count; i++){ if(db->contexts[i]){ if(!strcmp(db->contexts[i]->id, id)){ new_context = db->contexts[i]; break; } }else if(db->contexts[i] == NULL && null_index == -1){ null_index = i; break; } } if(!new_context){ /* id wasn't found, so generate a new context */ new_context = mqtt3_context_init(-1); if(!new_context){ return MOSQ_ERR_NOMEM; } if(null_index == -1){ /* There were no gaps in the db->contexts[] array, so need to append. */ db->context_count++; tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*db->context_count); if(tmp_contexts){ db->contexts = tmp_contexts; db->contexts[db->context_count-1] = new_context; }else{ _mosquitto_free(new_context); return MOSQ_ERR_NOMEM; } }else{ db->contexts[null_index] = new_context; } new_context->id = id; }else{ /* id was found, so context->id already in memory. */ _mosquitto_free(id); } new_context->bridge = bridge; new_context->is_bridge = true; new_context->username = new_context->bridge->username; new_context->password = new_context->bridge->password; #ifdef WITH_TLS new_context->tls_cafile = new_context->bridge->tls_cafile; new_context->tls_capath = new_context->bridge->tls_capath; new_context->tls_certfile = new_context->bridge->tls_certfile; new_context->tls_keyfile = new_context->bridge->tls_keyfile; new_context->tls_cert_reqs = SSL_VERIFY_PEER; new_context->tls_version = new_context->bridge->tls_version; new_context->tls_insecure = new_context->bridge->tls_insecure; #ifdef REAL_WITH_TLS_PSK new_context->tls_psk_identity = new_context->bridge->tls_psk_identity; new_context->tls_psk = new_context->bridge->tls_psk; #endif #endif bridge->try_private_accepted = true; return mqtt3_bridge_connect(db, new_context); }
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; }