int config__get_dir_files(const char *include_dir, char ***files, int *file_count) { char **l_files = NULL; int l_file_count = 0; char **files_tmp; int len; int i; DIR *dh; struct dirent *de; dh = opendir(include_dir); if(!dh){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open include_dir '%s'.", include_dir); return 1; } while((de = readdir(dh)) != NULL){ if(strlen(de->d_name) > 5){ if(!strcmp(&de->d_name[strlen(de->d_name)-5], ".conf")){ len = strlen(include_dir)+1+strlen(de->d_name)+1; l_file_count++; files_tmp = mosquitto__realloc(l_files, l_file_count*sizeof(char *)); if(!files_tmp){ for(i=0; i<l_file_count-1; i++){ mosquitto__free(l_files[i]); } mosquitto__free(l_files); closedir(dh); return MOSQ_ERR_NOMEM; } l_files = files_tmp; l_files[l_file_count-1] = mosquitto__malloc(len+1); if(!l_files[l_file_count-1]){ for(i=0; i<l_file_count-1; i++){ mosquitto__free(l_files[i]); } mosquitto__free(l_files); closedir(dh); return MOSQ_ERR_NOMEM; } snprintf(l_files[l_file_count-1], len, "%s/%s", include_dir, de->d_name); l_files[l_file_count-1][len] = '\0'; } } } closedir(dh); if(l_files){ qsort(l_files, l_file_count, sizeof(char *), scmp_p); } *files = l_files; *file_count = l_file_count; return 0; }
int config__get_dir_files(const char *include_dir, char ***files, int *file_count) { int len; int i; char **l_files = NULL; int l_file_count = 0; char **files_tmp; HANDLE fh; char dirpath[MAX_PATH]; WIN32_FIND_DATA find_data; snprintf(dirpath, MAX_PATH, "%s\\*.conf", include_dir); fh = FindFirstFile(dirpath, &find_data); if(fh == INVALID_HANDLE_VALUE){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open include_dir '%s'.", include_dir); return 1; } do{ len = strlen(include_dir)+1+strlen(find_data.cFileName)+1; l_file_count++; files_tmp = mosquitto__realloc(l_files, l_file_count*sizeof(char *)); if(!files_tmp){ for(i=0; i<l_file_count-1; i++){ mosquitto__free(l_files[i]); } mosquitto__free(l_files); FindClose(fh); return MOSQ_ERR_NOMEM; } l_files = files_tmp; l_files[l_file_count-1] = mosquitto__malloc(len+1); if(!l_files[l_file_count-1]){ for(i=0; i<l_file_count-1; i++){ mosquitto__free(l_files[i]); } mosquitto__free(l_files); FindClose(fh); return MOSQ_ERR_NOMEM; } snprintf(l_files[l_file_count-1], len, "%s/%s", include_dir, find_data.cFileName); l_files[l_file_count-1][len] = '\0'; }while(FindNextFile(fh, &find_data)); FindClose(fh); if(l_files){ qsort(l_files, l_file_count, sizeof(char *), scmp_p); } *files = l_files; *file_count = l_file_count; return 0; }
int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address) { #ifdef WITH_SRV char *h; int rc; if(!mosq) return MOSQ_ERR_INVAL; rc = ares_init(&mosq->achan); if(rc != ARES_SUCCESS){ return MOSQ_ERR_UNKNOWN; } if(!host){ // get local domain }else{ #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ h = mosquitto__malloc(strlen(host) + strlen("_secure-mqtt._tcp.") + 1); if(!h) return MOSQ_ERR_NOMEM; sprintf(h, "_secure-mqtt._tcp.%s", host); }else{ #endif h = mosquitto__malloc(strlen(host) + strlen("_mqtt._tcp.") + 1); if(!h) return MOSQ_ERR_NOMEM; sprintf(h, "_mqtt._tcp.%s", host); #ifdef WITH_TLS } #endif ares_search(mosq->achan, h, ns_c_in, ns_t_srv, srv_callback, mosq); mosquitto__free(h); } pthread_mutex_lock(&mosq->state_mutex); mosq->state = mosq_cs_connect_srv; pthread_mutex_unlock(&mosq->state_mutex); mosq->keepalive = keepalive; return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
int persist__chunk_client_msg_write_v5(FILE *db_fptr, struct P_client_msg *chunk) { struct PF_header header; struct mosquitto__packet prop_packet; uint16_t id_len = chunk->F.id_len; uint32_t proplen = 0; int rc; memset(&prop_packet, 0, sizeof(struct mosquitto__packet)); if(chunk->properties){ proplen = property__get_length_all(chunk->properties); proplen += packet__varint_bytes(proplen); } chunk->F.mid = htons(chunk->F.mid); chunk->F.id_len = htons(chunk->F.id_len); header.chunk = htonl(DB_CHUNK_CLIENT_MSG); header.length = htonl(sizeof(struct PF_client_msg) + id_len + proplen); write_e(db_fptr, &header, sizeof(struct PF_header)); write_e(db_fptr, &chunk->F, sizeof(struct PF_client_msg)); write_e(db_fptr, chunk->client_id, id_len); if(chunk->properties){ if(proplen > 0){ prop_packet.remaining_length = proplen; prop_packet.packet_length = proplen; prop_packet.payload = mosquitto__malloc(proplen); if(!prop_packet.payload){ return MOSQ_ERR_NOMEM; } rc = property__write_all(&prop_packet, chunk->properties, true); if(rc) return rc; write_e(db_fptr, prop_packet.payload, proplen); mosquitto__free(prop_packet.payload); } } return MOSQ_ERR_SUCCESS; error: log__printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; }
int handle__suback(struct mosquitto *mosq) { uint16_t mid; uint8_t qos; int *granted_qos; int qos_count; int i = 0; int rc; assert(mosq); #ifdef WITH_BROKER log__printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id); #else log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id); #endif rc = packet__read_uint16(&mosq->in_packet, &mid); if(rc) return rc; qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos; granted_qos = mosquitto__malloc(qos_count*sizeof(int)); if(!granted_qos) return MOSQ_ERR_NOMEM; while(mosq->in_packet.pos < mosq->in_packet.remaining_length){ rc = packet__read_byte(&mosq->in_packet, &qos); if(rc){ mosquitto__free(granted_qos); return rc; } granted_qos[i] = (int)qos; i++; } #ifndef WITH_BROKER pthread_mutex_lock(&mosq->callback_mutex); if(mosq->on_subscribe){ mosq->in_callback = true; mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos); mosq->in_callback = false; } pthread_mutex_unlock(&mosq->callback_mutex); #endif mosquitto__free(granted_qos); return MOSQ_ERR_SUCCESS; }
int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup) { #ifdef WITH_BROKER size_t len; #ifdef WITH_BRIDGE int i; struct mosquitto__bridge_topic *cur_topic; bool match; int rc; char *mapped_topic = NULL; char *topic_temp = NULL; #endif #endif assert(mosq); assert(topic); #if defined(WITH_BROKER) && defined(WITH_WEBSOCKETS) if(mosq->sock == INVALID_SOCKET && !mosq->wsi) return MOSQ_ERR_NO_CONN; #else if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; #endif #ifdef WITH_BROKER if(mosq->listener && mosq->listener->mount_point){ len = strlen(mosq->listener->mount_point); if(len < strlen(topic)){ topic += len; }else{ /* Invalid topic string. Should never happen, but silently swallow the message anyway. */ return MOSQ_ERR_SUCCESS; } } #ifdef WITH_BRIDGE if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){ for(i=0; i<mosq->bridge->topic_count; i++){ cur_topic = &mosq->bridge->topics[i]; if((cur_topic->direction == bd_both || cur_topic->direction == bd_out) && (cur_topic->remote_prefix || cur_topic->local_prefix)){ /* Topic mapping required on this topic if the message matches */ rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match); if(rc){ return rc; } if(match){ mapped_topic = mosquitto__strdup(topic); if(!mapped_topic) return MOSQ_ERR_NOMEM; if(cur_topic->local_prefix){ /* This prefix needs removing. */ if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){ topic_temp = mosquitto__strdup(mapped_topic+strlen(cur_topic->local_prefix)); mosquitto__free(mapped_topic); if(!topic_temp){ return MOSQ_ERR_NOMEM; } mapped_topic = topic_temp; } } if(cur_topic->remote_prefix){ /* This prefix needs adding. */ len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1; topic_temp = mosquitto__malloc(len+1); if(!topic_temp){ mosquitto__free(mapped_topic); return MOSQ_ERR_NOMEM; } snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic); topic_temp[len] = '\0'; mosquitto__free(mapped_topic); mapped_topic = topic_temp; } log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, mapped_topic, (long)payloadlen); G_PUB_BYTES_SENT_INC(payloadlen); rc = send__real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup); mosquitto__free(mapped_topic); return rc; } } } } #endif log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen); G_PUB_BYTES_SENT_INC(payloadlen); #else log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen); #endif return send__real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup); }
static char *http__canonical_filename( #ifndef LWS_LIBRARY_VERSION_NUMBER struct libwebsocket_context *context, #endif struct libwebsocket *wsi, const char *in, const char *http_dir) { size_t inlen, slen; char *filename, *filename_canonical; inlen = strlen(in); if(in[inlen-1] == '/'){ slen = strlen(http_dir) + inlen + strlen("/index.html") + 2; }else{ slen = strlen(http_dir) + inlen + 2; } filename = mosquitto__malloc(slen); if(!filename){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL); return NULL; } if(((char *)in)[inlen-1] == '/'){ snprintf(filename, slen, "%s%sindex.html", http_dir, (char *)in); }else{ snprintf(filename, slen, "%s%s", http_dir, (char *)in); } /* Get canonical path and check it is within our http_dir */ #ifdef WIN32 filename_canonical = _fullpath(NULL, filename, 0); mosquitto__free(filename); if(!filename_canonical){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL); return NULL; } #else filename_canonical = realpath(filename, NULL); mosquitto__free(filename); if(!filename_canonical){ if(errno == EACCES){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL); }else if(errno == EINVAL || errno == EIO || errno == ELOOP){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL); }else if(errno == ENAMETOOLONG){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_REQ_URI_TOO_LONG, NULL); }else if(errno == ENOENT || errno == ENOTDIR){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_NOT_FOUND, NULL); } return NULL; } #endif if(strncmp(http_dir, filename_canonical, strlen(http_dir))){ /* Requested file isn't within http_dir, deny access. */ free(filename_canonical); libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL); return NULL; } return filename_canonical; }
static int callback_mqtt(struct libwebsocket_context *context, #endif struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) { struct mosquitto_db *db; struct mosquitto *mosq = NULL; struct mosquitto__packet *packet; int count, i, j; const struct libwebsocket_protocols *p; struct libws_mqtt_data *u = (struct libws_mqtt_data *)user; size_t pos; uint8_t *buf; int rc; uint8_t byte; db = &int_db; switch (reason) { case LWS_CALLBACK_ESTABLISHED: mosq = context__init(db, WEBSOCKET_CLIENT); if(mosq){ p = libwebsockets_get_protocol(wsi); for (i=0; i<db->config->listener_count; i++){ if (db->config->listeners[i].protocol == mp_websockets) { for (j=0; db->config->listeners[i].ws_protocol[j].name; j++){ if (p == &db->config->listeners[i].ws_protocol[j]){ mosq->listener = &db->config->listeners[i]; mosq->listener->client_count++; } } } } if(!mosq->listener){ mosquitto__free(mosq); return -1; } #if !defined(LWS_LIBRARY_VERSION_NUMBER) mosq->ws_context = context; #endif mosq->wsi = wsi; #ifdef WITH_TLS if(in){ mosq->ssl = (SSL *)in; if(!mosq->listener->ssl_ctx){ mosq->listener->ssl_ctx = SSL_get_SSL_CTX(mosq->ssl); } } #endif u->mosq = mosq; }else{ return -1; } easy_address(libwebsocket_get_socket_fd(wsi), mosq); if(!mosq->address){ /* getpeername and inet_ntop failed and not a bridge */ mosquitto__free(mosq); u->mosq = NULL; return -1; } if(mosq->listener->max_connections > 0 && mosq->listener->client_count > mosq->listener->max_connections){ if(db->config->connection_messages == true){ log__printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied: max_connections exceeded.", mosq->address); } mosquitto__free(mosq); u->mosq = NULL; return -1; } mosq->sock = libwebsocket_get_socket_fd(wsi); HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(mosq->sock), mosq); break; case LWS_CALLBACK_CLOSED: if(!u){ return -1; } mosq = u->mosq; if(mosq){ if(mosq->sock != INVALID_SOCKET){ HASH_DELETE(hh_sock, db->contexts_by_sock, mosq); mosq->sock = INVALID_SOCKET; mosq->pollfd_index = -1; } mosq->wsi = NULL; #ifdef WITH_TLS mosq->ssl = NULL; #endif do_disconnect(db, mosq); } break; case LWS_CALLBACK_SERVER_WRITEABLE: if(!u){ return -1; } mosq = u->mosq; if(!mosq){ return -1; } db__message_write(db, mosq); if(mosq->out_packet && !mosq->current_out_packet){ mosq->current_out_packet = mosq->out_packet; mosq->out_packet = mosq->out_packet->next; if(!mosq->out_packet){ mosq->out_packet_last = NULL; } } if(mosq->current_out_packet && !lws_send_pipe_choked(mosq->wsi)){ packet = mosq->current_out_packet; if(packet->pos == 0 && packet->to_process == packet->packet_length){ /* First time this packet has been dealt with. * libwebsockets requires that the payload has * LWS_SEND_BUFFER_PRE_PADDING space available before the * actual data and LWS_SEND_BUFFER_POST_PADDING afterwards. * We've already made the payload big enough to allow this, * but need to move it into position here. */ memmove(&packet->payload[LWS_SEND_BUFFER_PRE_PADDING], packet->payload, packet->packet_length); packet->pos += LWS_SEND_BUFFER_PRE_PADDING; } count = libwebsocket_write(wsi, &packet->payload[packet->pos], packet->to_process, LWS_WRITE_BINARY); if(count < 0){ if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){ return -1; } return 0; } #ifdef WITH_SYS_TREE g_bytes_sent += count; #endif packet->to_process -= count; packet->pos += count; if(packet->to_process > 0){ if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){ return -1; } break; } #ifdef WITH_SYS_TREE g_msgs_sent++; if(((packet->command)&0xF6) == PUBLISH){ g_pub_msgs_sent++; } #endif /* Free data and reset values */ mosq->current_out_packet = mosq->out_packet; if(mosq->out_packet){ mosq->out_packet = mosq->out_packet->next; if(!mosq->out_packet){ mosq->out_packet_last = NULL; } } packet__cleanup(packet); mosquitto__free(packet); mosq->next_msg_out = mosquitto_time() + mosq->keepalive; } if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){ return -1; } if(mosq->current_out_packet){ libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi); } break; case LWS_CALLBACK_RECEIVE: if(!u || !u->mosq){ return -1; } mosq = u->mosq; pos = 0; buf = (uint8_t *)in; G_BYTES_RECEIVED_INC(len); while(pos < len){ if(!mosq->in_packet.command){ mosq->in_packet.command = buf[pos]; pos++; /* Clients must send CONNECT as their first command. */ if(mosq->state == mosq_cs_new && (mosq->in_packet.command&0xF0) != CONNECT){ return -1; } } if(mosq->in_packet.remaining_count <= 0){ do{ if(pos == len){ return 0; } byte = buf[pos]; pos++; mosq->in_packet.remaining_count--; /* Max 4 bytes length for remaining length as defined by protocol. * Anything more likely means a broken/malicious client. */ if(mosq->in_packet.remaining_count < -4){ return -1; } mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult; mosq->in_packet.remaining_mult *= 128; }while((byte & 128) != 0); mosq->in_packet.remaining_count *= -1; if(mosq->in_packet.remaining_length > 0){ mosq->in_packet.payload = mosquitto__malloc(mosq->in_packet.remaining_length*sizeof(uint8_t)); if(!mosq->in_packet.payload){ return -1; } mosq->in_packet.to_process = mosq->in_packet.remaining_length; } } if(mosq->in_packet.to_process>0){ if(len - pos >= mosq->in_packet.to_process){ memcpy(&mosq->in_packet.payload[mosq->in_packet.pos], &buf[pos], mosq->in_packet.to_process); mosq->in_packet.pos += mosq->in_packet.to_process; pos += mosq->in_packet.to_process; mosq->in_packet.to_process = 0; }else{ memcpy(&mosq->in_packet.payload[mosq->in_packet.pos], &buf[pos], len-pos); mosq->in_packet.pos += len-pos; mosq->in_packet.to_process -= len-pos; return 0; } } /* All data for this packet is read. */ mosq->in_packet.pos = 0; #ifdef WITH_SYS_TREE G_MSGS_RECEIVED_INC(1); if(((mosq->in_packet.command)&0xF5) == PUBLISH){ G_PUB_MSGS_RECEIVED_INC(1); } #endif rc = handle__packet(db, mosq); /* Free data and reset values */ packet__cleanup(&mosq->in_packet); mosq->last_msg_in = mosquitto_time(); if(rc && (mosq->out_packet || mosq->current_out_packet)) { if(mosq->state != mosq_cs_disconnecting){ mosq->state = mosq_cs_disconnect_ws; } libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi); } else if (rc) { do_disconnect(db, mosq); return -1; } } break; default: break; } return 0; }
int handle__unsubscribe(struct mosquitto_db *db, struct mosquitto *context) { uint16_t mid; char *sub; int slen; int rc; uint8_t reason; int reason_code_count = 0; int reason_code_max; uint8_t *reason_codes = NULL, *reason_tmp; mosquitto_property *properties = NULL; if(!context) return MOSQ_ERR_INVAL; if(context->state != mosq_cs_connected){ return MOSQ_ERR_PROTOCOL; } log__printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBSCRIBE from %s", context->id); if(context->protocol != mosq_p_mqtt31){ if((context->in_packet.command&0x0F) != 0x02){ return MOSQ_ERR_PROTOCOL; } } if(packet__read_uint16(&context->in_packet, &mid)) return 1; if(mid == 0) return MOSQ_ERR_PROTOCOL; if(context->protocol == mosq_p_mqtt5){ rc = property__read_all(CMD_UNSUBSCRIBE, &context->in_packet, &properties); if(rc) return rc; /* Immediately free, we don't do anything with User Property at the moment */ mosquitto_property_free_all(&properties); } if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt5){ if(context->in_packet.pos == context->in_packet.remaining_length){ /* No topic specified, protocol error. */ return MOSQ_ERR_PROTOCOL; } } reason_code_max = 10; reason_codes = mosquitto__malloc(reason_code_max); if(!reason_codes){ return MOSQ_ERR_NOMEM; } while(context->in_packet.pos < context->in_packet.remaining_length){ sub = NULL; if(packet__read_string(&context->in_packet, &sub, &slen)){ return 1; } if(!slen){ log__printf(NULL, MOSQ_LOG_INFO, "Empty unsubscription string from %s, disconnecting.", context->id); mosquitto__free(sub); return 1; } if(mosquitto_sub_topic_check(sub)){ log__printf(NULL, MOSQ_LOG_INFO, "Invalid unsubscription string from %s, disconnecting.", context->id); mosquitto__free(sub); return 1; } log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub); rc = sub__remove(db, context, sub, db->subs, &reason); log__printf(NULL, MOSQ_LOG_UNSUBSCRIBE, "%s %s", context->id, sub); mosquitto__free(sub); if(rc) return rc; reason_codes[reason_code_count] = reason; reason_code_count++; if(reason_code_count == reason_code_max){ reason_tmp = mosquitto__realloc(reason_codes, reason_code_max*2); if(!reason_tmp){ mosquitto__free(reason_codes); return MOSQ_ERR_NOMEM; } reason_codes = reason_tmp; reason_code_max *= 2; } } #ifdef WITH_PERSISTENCE db->persistence_changes++; #endif log__printf(NULL, MOSQ_LOG_DEBUG, "Sending UNSUBACK to %s", context->id); /* We don't use Reason String or User Property yet. */ rc = send__unsuback(context, mid, reason_code_count, reason_codes, NULL); mosquitto__free(reason_codes); return rc; }
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 persist__chunk_message_store_write_v5(FILE *db_fptr, struct P_msg_store *chunk) { struct PF_header header; uint32_t payloadlen = chunk->F.payloadlen; uint16_t source_id_len = chunk->F.source_id_len; uint16_t source_username_len = chunk->F.source_username_len; uint16_t topic_len = chunk->F.topic_len; uint32_t proplen = 0; struct mosquitto__packet prop_packet; int rc; memset(&prop_packet, 0, sizeof(struct mosquitto__packet)); if(chunk->properties){ proplen = property__get_length_all(chunk->properties); proplen += packet__varint_bytes(proplen); } chunk->F.payloadlen = htonl(chunk->F.payloadlen); chunk->F.source_mid = htons(chunk->F.source_mid); chunk->F.source_id_len = htons(chunk->F.source_id_len); chunk->F.source_username_len = htons(chunk->F.source_username_len); chunk->F.topic_len = htons(chunk->F.topic_len); chunk->F.source_port = htons(chunk->F.source_port); header.chunk = htonl(DB_CHUNK_MSG_STORE); header.length = htonl(sizeof(struct PF_msg_store) + topic_len + payloadlen + source_id_len + source_username_len + proplen); write_e(db_fptr, &header, sizeof(struct PF_header)); write_e(db_fptr, &chunk->F, sizeof(struct PF_msg_store)); if(source_id_len){ write_e(db_fptr, chunk->source.id, source_id_len); } if(source_username_len){ write_e(db_fptr, chunk->source.username, source_username_len); } write_e(db_fptr, chunk->topic, topic_len); if(payloadlen){ write_e(db_fptr, UHPA_ACCESS(chunk->payload, payloadlen), (unsigned int)payloadlen); } if(chunk->properties){ if(proplen > 0){ prop_packet.remaining_length = proplen; prop_packet.packet_length = proplen; prop_packet.payload = mosquitto__malloc(proplen); if(!prop_packet.payload){ return MOSQ_ERR_NOMEM; } rc = property__write_all(&prop_packet, chunk->properties, true); if(rc) return rc; write_e(db_fptr, prop_packet.payload, proplen); mosquitto__free(prop_packet.payload); } } return MOSQ_ERR_SUCCESS; error: log__printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); mosquitto__free(prop_packet.payload); return 1; }
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; }