int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers) { #ifdef WITH_TLS if(!mosq) return MOSQ_ERR_INVAL; mosq->tls_cert_reqs = cert_reqs; if(tls_version) { if(!strcasecmp(tls_version, "tlsv1")) { mosq->tls_version = _mosquitto_strdup(tls_version); if(!mosq->tls_version) return MOSQ_ERR_NOMEM; } else { return MOSQ_ERR_INVAL; } } else { mosq->tls_version = _mosquitto_strdup("tlsv1"); if(!mosq->tls_version) return MOSQ_ERR_NOMEM; } if(ciphers) { mosq->tls_ciphers = _mosquitto_strdup(ciphers); if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; } else { mosq->tls_ciphers = NULL; } return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers) { #ifdef REAL_WITH_TLS_PSK if(!mosq || !psk || !identity) return MOSQ_ERR_INVAL; /* Check for hex only digits */ if(strspn(psk, "0123456789abcdefABCDEF") < strlen(psk)){ return MOSQ_ERR_INVAL; } mosq->tls_psk = _mosquitto_strdup(psk); if(!mosq->tls_psk) return MOSQ_ERR_NOMEM; mosq->tls_psk_identity = _mosquitto_strdup(identity); if(!mosq->tls_psk_identity){ _mosquitto_free(mosq->tls_psk); return MOSQ_ERR_NOMEM; } if(ciphers){ mosq->tls_ciphers = _mosquitto_strdup(ciphers); if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; }else{ mosq->tls_ciphers = NULL; } return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password) { if(!mosq) return MOSQ_ERR_INVAL; if(mosq->username){ _mosquitto_free(mosq->username); mosq->username = NULL; } if(mosq->password){ _mosquitto_free(mosq->password); mosq->password = NULL; } if(username){ mosq->username = _mosquitto_strdup(username); if(!mosq->username) return MOSQ_ERR_NOMEM; if(password){ mosq->password = _mosquitto_strdup(password); if(!mosq->password){ _mosquitto_free(mosq->username); mosq->username = NULL; return MOSQ_ERR_NOMEM; } } } return MOSQ_ERR_SUCCESS; }
static int _mosquitto_connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address) { if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; if(mosq->bind_address) _mosquitto_free(mosq->bind_address); if(bind_address){ mosq->bind_address = _mosquitto_strdup(bind_address); if(!mosq->bind_address) return MOSQ_ERR_NOMEM; } mosq->keepalive = keepalive; if(mosq->sockpairR != INVALID_SOCKET){ COMPAT_CLOSE(mosq->sockpairR); mosq->sockpairR = INVALID_SOCKET; } if(mosq->sockpairW != INVALID_SOCKET){ COMPAT_CLOSE(mosq->sockpairW); mosq->sockpairW = INVALID_SOCKET; } if(_mosquitto_socketpair(&mosq->sockpairR, &mosq->sockpairW)){ _mosquitto_log_printf(mosq, MOSQ_LOG_WARNING, "Warning: Unable to open socket pair, outgoing publish commands may be delayed."); } return MOSQ_ERR_SUCCESS; }
static int _sub_add(struct mosquitto_db *db, struct mosquitto *context, int qos, struct _mosquitto_subhier *subhier, struct _sub_token *tokens) { struct _mosquitto_subhier *branch, *last = NULL; struct _mosquitto_subleaf *leaf, *last_leaf; if(!tokens){ if(context){ leaf = subhier->subs; last_leaf = NULL; while(leaf){ if(!strcmp(leaf->context->id, context->id)){ /* Client making a second subscription to same topic. Only * need to update QoS. Return -1 to indicate this to the * calling function. */ leaf->qos = qos; return -1; } last_leaf = leaf; leaf = leaf->next; } leaf = _mosquitto_malloc(sizeof(struct _mosquitto_subleaf)); if(!leaf) return MOSQ_ERR_NOMEM; leaf->next = NULL; leaf->context = context; leaf->qos = qos; if(last_leaf){ last_leaf->next = leaf; leaf->prev = last_leaf; }else{ subhier->subs = leaf; leaf->prev = NULL; } db->subscription_count++; } return MOSQ_ERR_SUCCESS; } branch = subhier->children; while(branch){ if(!strcmp(branch->topic, tokens->topic)){ return _sub_add(db, context, qos, branch, tokens->next); } last = branch; branch = branch->next; } /* Not found */ branch = _mosquitto_calloc(1, sizeof(struct _mosquitto_subhier)); if(!branch) return MOSQ_ERR_NOMEM; branch->topic = _mosquitto_strdup(tokens->topic); if(!branch->topic){ _mosquitto_free(branch); return MOSQ_ERR_NOMEM; } if(!last){ subhier->children = branch; }else{ last->next = branch; } return _sub_add(db, context, qos, branch, tokens->next); }
int mqtt3_pwfile_parse(struct _mosquitto_db *db) { FILE *pwfile; struct _mosquitto_unpwd *unpwd; char buf[256]; char *username, *password; int len; if(!db || !db->config) return MOSQ_ERR_INVAL; if(!db->config->password_file) return MOSQ_ERR_SUCCESS; pwfile = fopen(db->config->password_file, "rt"); if(!pwfile) return 1; while(!feof(pwfile)){ if(fgets(buf, 256, pwfile)){ username = strtok(buf, ":"); if(username){ unpwd = _mosquitto_calloc(1, sizeof(struct _mosquitto_unpwd)); if(!unpwd) return MOSQ_ERR_NOMEM; unpwd->username = _mosquitto_strdup(username); if(!unpwd->username) return MOSQ_ERR_NOMEM; len = strlen(unpwd->username); while(unpwd->username[len-1] == 10 || unpwd->username[len-1] == 13){ unpwd->username[len-1] = '\0'; len = strlen(unpwd->username); } password = strtok(NULL, ":"); if(password){ unpwd->password = _mosquitto_strdup(password); if(!unpwd->password) return MOSQ_ERR_NOMEM; len = strlen(unpwd->password); while(unpwd->password[len-1] == 10 || unpwd->password[len-1] == 13){ unpwd->password[len-1] = '\0'; len = strlen(unpwd->password); } } unpwd->next = db->unpwd; db->unpwd = unpwd; } } } fclose(pwfile); return MOSQ_ERR_SUCCESS; }
int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers) { #ifdef WITH_TLS if(!mosq) return MOSQ_ERR_INVAL; mosq->tls_cert_reqs = cert_reqs; if(tls_version){ #if OPENSSL_VERSION_NUMBER >= 0x10001000L if(!strcasecmp(tls_version, "tlsv1.2") || !strcasecmp(tls_version, "tlsv1.1") || !strcasecmp(tls_version, "tlsv1")){ mosq->tls_version = _mosquitto_strdup(tls_version); if(!mosq->tls_version) return MOSQ_ERR_NOMEM; }else{ return MOSQ_ERR_INVAL; } #else if(!strcasecmp(tls_version, "tlsv1")){ mosq->tls_version = _mosquitto_strdup(tls_version); if(!mosq->tls_version) return MOSQ_ERR_NOMEM; }else{ return MOSQ_ERR_INVAL; } #endif }else{ #if OPENSSL_VERSION_NUMBER >= 0x10001000L mosq->tls_version = _mosquitto_strdup("tlsv1.2"); #else mosq->tls_version = _mosquitto_strdup("tlsv1"); #endif if(!mosq->tls_version) return MOSQ_ERR_NOMEM; } if(ciphers){ mosq->tls_ciphers = _mosquitto_strdup(ciphers); if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; }else{ mosq->tls_ciphers = NULL; } return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain) { int rc = MOSQ_ERR_SUCCESS; if(!mosq || !topic) return MOSQ_ERR_INVAL; if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL; if(mosquitto_pub_topic_check(topic)) return MOSQ_ERR_INVAL; if(mosq->will){ if(mosq->will->topic){ _mosquitto_free(mosq->will->topic); mosq->will->topic = NULL; } if(mosq->will->payload){ _mosquitto_free(mosq->will->payload); mosq->will->payload = NULL; } _mosquitto_free(mosq->will); mosq->will = NULL; } mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); if(!mosq->will) return MOSQ_ERR_NOMEM; mosq->will->topic = _mosquitto_strdup(topic); if(!mosq->will->topic){ rc = MOSQ_ERR_NOMEM; goto cleanup; } mosq->will->payloadlen = payloadlen; if(mosq->will->payloadlen > 0){ if(!payload){ rc = MOSQ_ERR_INVAL; goto cleanup; } mosq->will->payload = _mosquitto_malloc(sizeof(char)*mosq->will->payloadlen); if(!mosq->will->payload){ rc = MOSQ_ERR_NOMEM; goto cleanup; } memcpy(mosq->will->payload, payload, payloadlen); } mosq->will->qos = qos; mosq->will->retain = retain; return MOSQ_ERR_SUCCESS; cleanup: if(mosq->will){ if(mosq->will->topic) _mosquitto_free(mosq->will->topic); if(mosq->will->payload) _mosquitto_free(mosq->will->payload); } _mosquitto_free(mosq->will); mosq->will = NULL; return rc; }
int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain) { struct mosquitto_message_all *message; uint16_t local_mid; if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL; if(strlen(topic) == 0) return MOSQ_ERR_INVAL; if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; if(_mosquitto_topic_wildcard_len_check(topic) != MOSQ_ERR_SUCCESS) { return MOSQ_ERR_INVAL; } //获取总共发送信息数,并加1返回 local_mid = _mosquitto_mid_generate(mosq); if(mid) { *mid = local_mid; } if(qos == 0) { return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false); } else { message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); if(!message) return MOSQ_ERR_NOMEM; message->next = NULL; message->timestamp = time(NULL); message->direction = mosq_md_out; if(qos == 1) { message->state = mosq_ms_wait_puback; } else if(qos == 2) { message->state = mosq_ms_wait_pubrec; } message->msg.mid = local_mid; message->msg.topic = _mosquitto_strdup(topic); if(!message->msg.topic) { _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } if(payloadlen) { message->msg.payloadlen = payloadlen; message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t)); if(!message->msg.payload) { _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); } else { message->msg.payloadlen = 0; message->msg.payload = NULL; } message->msg.qos = qos; message->msg.retain = retain; message->dup = false; _mosquitto_message_queue(mosq, message); return _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); } }
int _mosquitto_will_set(struct mosquitto *mosq, bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { int rc = MOSQ_ERR_SUCCESS; if(!mosq || (will && !topic)) return MOSQ_ERR_INVAL; if(payloadlen > 268435455) return MOSQ_ERR_PAYLOAD_SIZE; if(mosq->will){ if(mosq->will->topic){ _mosquitto_free(mosq->will->topic); mosq->will->topic = NULL; } if(mosq->will->payload){ _mosquitto_free(mosq->will->payload); mosq->will->payload = NULL; } _mosquitto_free(mosq->will); mosq->will = NULL; } if(will){ mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); if(!mosq->will) return MOSQ_ERR_NOMEM; mosq->will->topic = _mosquitto_strdup(topic); if(!mosq->will->topic){ rc = MOSQ_ERR_NOMEM; goto cleanup; } mosq->will->payloadlen = payloadlen; if(mosq->will->payloadlen > 0){ if(!payload){ rc = MOSQ_ERR_INVAL; goto cleanup; } mosq->will->payload = _mosquitto_malloc(sizeof(uint8_t)*mosq->will->payloadlen); if(!mosq->will->payload){ rc = MOSQ_ERR_NOMEM; goto cleanup; } memcpy(mosq->will->payload, payload, payloadlen); } mosq->will->qos = qos; mosq->will->retain = retain; } return MOSQ_ERR_SUCCESS; cleanup: if(mosq->will){ if(mosq->will->topic) _mosquitto_free(mosq->will->topic); if(mosq->will->payload) _mosquitto_free(mosq->will->payload); } _mosquitto_free(mosq->will); mosq->will = NULL; return rc; }
int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, const char *username, const char *password) { #ifdef WITH_SOCKS if(!mosq) return MOSQ_ERR_INVAL; if(!host || strlen(host) > 256) return MOSQ_ERR_INVAL; if(port < 1 || port > 65535) return MOSQ_ERR_INVAL; if(mosq->socks5_host){ _mosquitto_free(mosq->socks5_host); } mosq->socks5_host = _mosquitto_strdup(host); if(!mosq->socks5_host){ return MOSQ_ERR_NOMEM; } mosq->socks5_port = port; if(mosq->socks5_username){ _mosquitto_free(mosq->socks5_username); } if(mosq->socks5_password){ _mosquitto_free(mosq->socks5_password); } if(username){ mosq->socks5_username = _mosquitto_strdup(username); if(!mosq->socks5_username){ return MOSQ_ERR_NOMEM; } if(password){ mosq->socks5_password = _mosquitto_strdup(password); if(!mosq->socks5_password){ _mosquitto_free(mosq->socks5_username); return MOSQ_ERR_NOMEM; } } } return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
mqtt3_context *mqtt3_context_init(int sock) { mqtt3_context *context; struct sockaddr_storage addr; socklen_t addrlen; char address[1024]; context = _mosquitto_malloc(sizeof(mqtt3_context)); if(!context) return NULL; context->core.state = mosq_cs_new; context->duplicate = false; context->core.sock = sock; context->core.last_msg_in = time(NULL); context->core.last_msg_out = time(NULL); context->core.keepalive = 60; /* Default to 60s */ context->clean_session = true; context->core.id = NULL; context->core.last_mid = 0; context->core.will = NULL; context->core.username = NULL; context->core.password = NULL; context->core.in_packet.payload = NULL; _mosquitto_packet_cleanup(&context->core.in_packet); context->core.out_packet = NULL; addrlen = sizeof(addr); context->address = NULL; if(!getpeername(sock, (struct sockaddr *)&addr, &addrlen)){ if(addr.ss_family == AF_INET){ if(inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr.s_addr, address, 1024)){ context->address = _mosquitto_strdup(address); } }else if(addr.ss_family == AF_INET6){ if(inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr.s6_addr, address, 1024)){ context->address = _mosquitto_strdup(address); } } } context->bridge = NULL; context->msgs = NULL; return context; }
struct mosquitto *mqtt3_context_init(struct mosquitto_db *db, mosq_sock_t sock) { struct mosquitto *context; char address[1024]; context = _mosquitto_calloc(1, sizeof(struct mosquitto)); if(!context) return NULL; context->state = mosq_cs_new; context->sock = sock; context->last_msg_in = mosquitto_time(); context->next_msg_out = mosquitto_time() + 60; context->keepalive = 60; /* Default to 60s */ context->clean_session = true; context->disconnect_t = 0; context->id = NULL; context->last_mid = 0; context->will = NULL; context->username = NULL; context->password = NULL; context->listener = NULL; context->acl_list = NULL; /* is_bridge records whether this client is a bridge or not. This could be * done by looking at context->bridge for bridges that we create ourself, * but incoming bridges need some other way of being recorded. */ context->is_bridge = false; context->in_packet.payload = NULL; _mosquitto_packet_cleanup(&context->in_packet); context->out_packet = NULL; context->current_out_packet = NULL; context->address = NULL; if((int)sock >= 0){ if(!_mosquitto_socket_get_address(sock, address, 1024)){ context->address = _mosquitto_strdup(address); } if(!context->address){ /* getpeername and inet_ntop failed and not a bridge */ _mosquitto_free(context); return NULL; } } context->bridge = NULL; context->msgs = NULL; context->last_msg = NULL; context->msg_count = 0; context->msg_count12 = 0; #ifdef WITH_TLS context->ssl = NULL; #endif if((int)context->sock >= 0){ HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(context->sock), context); } return context; }
int mqtt3_sub_add(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int qos, struct _mosquitto_subhier *root) { int rc = 0; struct _mosquitto_subhier *subhier, *child; struct _sub_token *tokens = NULL, *tail; assert(root); assert(sub); if(_sub_topic_tokenise(sub, &tokens)) return 1; subhier = root->children; while(subhier){ if(!strcmp(subhier->topic, tokens->topic)){ rc = _sub_add(db, context, qos, subhier, tokens); break; } subhier = subhier->next; } if(!subhier){ child = _mosquitto_malloc(sizeof(struct _mosquitto_subhier)); if(!child){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->topic = _mosquitto_strdup(tokens->topic); if(!child->topic){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->subs = NULL; child->children = NULL; child->retained = NULL; if(db->subs.children){ child->next = db->subs.children; }else{ child->next = NULL; } db->subs.children = child; rc = _sub_add(db, context, qos, child, tokens); } while(tokens){ tail = tokens->next; _mosquitto_free(tokens->topic); _mosquitto_free(tokens); tokens = tail; } /* We aren't worried about -1 (already subscribed) return codes. */ if(rc == -1) rc = MOSQ_ERR_SUCCESS; return rc; }
static int _mosquitto_connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address) { if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; if(mosq->bind_address) _mosquitto_free(mosq->bind_address); if(bind_address){ mosq->bind_address = _mosquitto_strdup(bind_address); if(!mosq->bind_address) return MOSQ_ERR_NOMEM; } mosq->keepalive = keepalive; _mosquitto_socketpair(&mosq->sockpairR, &mosq->sockpairW); return MOSQ_ERR_SUCCESS; }
int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive, bool clean_session) { if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; mosq->keepalive = keepalive; mosq->clean_session = clean_session; return mosquitto_reconnect(mosq); }
int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive) { if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; mosq->keepalive = keepalive; pthread_mutex_lock(&mosq->state_mutex); mosq->state = mosq_cs_connect_async; pthread_mutex_unlock(&mosq->state_mutex); return MOSQ_ERR_SUCCESS; }
struct mosquitto *mosquitto_new(const char *id, void *obj) { struct mosquitto *mosq = NULL; if(!id) return NULL; mosq = (struct mosquitto *)_mosquitto_calloc(1, sizeof(struct mosquitto)); if(mosq){ if(obj){ mosq->obj = obj; }else{ mosq->obj = mosq; } mosq->sock = INVALID_SOCKET; mosq->keepalive = 60; mosq->message_retry = 20; mosq->last_retry_check = 0; mosq->id = _mosquitto_strdup(id); mosq->username = NULL; mosq->password = NULL; mosq->in_packet.payload = NULL; _mosquitto_packet_cleanup(&mosq->in_packet); mosq->out_packet = NULL; mosq->last_msg_in = time(NULL); mosq->last_msg_out = time(NULL); mosq->last_mid = 0; mosq->state = mosq_cs_new; mosq->messages = NULL; mosq->will = NULL; mosq->on_connect = NULL; mosq->on_publish = NULL; mosq->on_message = NULL; mosq->on_subscribe = NULL; mosq->on_unsubscribe = NULL; mosq->log_destinations = MOSQ_LOG_NONE; mosq->log_priorities = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO; mosq->host = NULL; mosq->port = 1883; mosq->in_callback = false; #ifdef WITH_SSL mosq->ssl = NULL; #endif } return mosq; }
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); }
/* * Function: mosquitto_connect_async * * 连接MQTT服务器接口。此接口为异步连接接口。 * 如果需要调用<mosquitto_connect_async>接口,客户端必须线程调用 * <mosquitto_loop_start>接口。若想用<mosquitto_loop>,则必须调用 * <mosquitto_connect>连接服务器。 * * 可以在调用<mosquitto_loop_start>前或者后调用此接口 * * Parameters: * mosq - 一个初始化的mosquitto对象 * host - 连接的服务器地址或IP地址 * port - 连接端口,默认为1883 * keepalive - 检测当前是否在线的周期秒数。 * 在检测的时候客户端会发送PING命令,待接收到返回信息后更新网络连接状态 * 发送周期起始时间为最后一个发送的信息时间或PING命令时间之后开始算起。 * * Returns: * MOSQ_ERR_SUCCESS - 连接成功 * MOSQ_ERR_INVAL - 输入参数异常 * MOSQ_ERR_NOMEM - 内存异常 * MOSQ_ERR_ERRNO - ???:未知错误类型 * */ int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive) { //输入参数是否正规的判断 if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; //修改服务器地址和端口 if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; //设置检测在线状态周期 mosq->keepalive = keepalive; //更新连接状态 pthread_mutex_lock(&mosq->state_mutex); mosq->state = mosq_cs_connect_async; pthread_mutex_unlock(&mosq->state_mutex); return MOSQ_ERR_SUCCESS; }
static struct mosquitto *_db_find_or_add_context(mosquitto_db *db, const char *client_id, uint16_t last_mid) { struct mosquitto *context; struct mosquitto **tmp_contexts; int i; context = NULL; for(i=0; i<db->context_count; i++){ if(db->contexts[i] && !strcmp(db->contexts[i]->id, client_id)){ context = db->contexts[i]; break; } } if(!context){ context = mqtt3_context_init(-1); context->clean_session = false; for(i=0; i<db->context_count; i++){ if(!db->contexts[i]){ db->contexts[i] = context; break; } } if(i==db->context_count){ 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] = context; }else{ return NULL; } } context->id = _mosquitto_strdup(client_id); } if(last_mid){ context->last_mid = last_mid; } return context; }
static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) { struct _mosquitto_db *db; struct mosquitto *context; struct _mqtt3_listener *listener; char *psk_key = NULL; int len; const char *psk_hint; if(!identity) return 0; db = _mosquitto_get_db(); context = SSL_get_ex_data(ssl, tls_ex_index_context); if(!context) return 0; listener = SSL_get_ex_data(ssl, tls_ex_index_listener); if(!listener) return 0; psk_hint = listener->psk_hint; /* The hex to BN conversion results in the length halving, so we can pass * max_psk_len*2 as the max hex key here. */ psk_key = _mosquitto_calloc(1, max_psk_len*2 + 1); if(!psk_key) return 0; if(mosquitto_psk_key_get(db, psk_hint, identity, psk_key, max_psk_len*2) != MOSQ_ERR_SUCCESS){ return 0; } len = _mosquitto_hex2bin(psk_key, psk, max_psk_len); if (len < 0) return 0; if(listener->use_identity_as_username){ context->username = _mosquitto_strdup(identity); if(!context->username) return 0; } return len; }
int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src) { if(!dst || !src) return MOSQ_ERR_INVAL; dst->mid = src->mid; dst->topic = _mosquitto_strdup(src->topic); if(!dst->topic) return MOSQ_ERR_NOMEM; dst->qos = src->qos; dst->retain = src->retain; if(src->payloadlen){ dst->payload = _mosquitto_malloc(src->payloadlen); if(!dst->payload){ _mosquitto_free(dst->topic); return MOSQ_ERR_NOMEM; } memcpy(dst->payload, src->payload, src->payloadlen); dst->payloadlen = src->payloadlen; }else{ dst->payloadlen = 0; dst->payload = NULL; } return MOSQ_ERR_SUCCESS; }
int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *capath, const char *certfile, const char *keyfile, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)) { #ifdef WITH_TLS FILE *fptr; if(!mosq || (!cafile && !capath) || (certfile && !keyfile) || (!certfile && keyfile)) return MOSQ_ERR_INVAL; if(cafile){ fptr = _mosquitto_fopen(cafile, "rt"); if(fptr){ fclose(fptr); }else{ return MOSQ_ERR_INVAL; } mosq->tls_cafile = _mosquitto_strdup(cafile); if(!mosq->tls_cafile){ return MOSQ_ERR_NOMEM; } }else if(mosq->tls_cafile){ _mosquitto_free(mosq->tls_cafile); mosq->tls_cafile = NULL; } if(capath){ mosq->tls_capath = _mosquitto_strdup(capath); if(!mosq->tls_capath){ return MOSQ_ERR_NOMEM; } }else if(mosq->tls_capath){ _mosquitto_free(mosq->tls_capath); mosq->tls_capath = NULL; } if(certfile){ fptr = _mosquitto_fopen(certfile, "rt"); if(fptr){ fclose(fptr); }else{ if(mosq->tls_cafile){ _mosquitto_free(mosq->tls_cafile); mosq->tls_cafile = NULL; } if(mosq->tls_capath){ _mosquitto_free(mosq->tls_capath); mosq->tls_capath = NULL; } return MOSQ_ERR_INVAL; } mosq->tls_certfile = _mosquitto_strdup(certfile); if(!mosq->tls_certfile){ return MOSQ_ERR_NOMEM; } }else{ if(mosq->tls_certfile) _mosquitto_free(mosq->tls_certfile); mosq->tls_certfile = NULL; } if(keyfile){ fptr = _mosquitto_fopen(keyfile, "rt"); if(fptr){ fclose(fptr); }else{ if(mosq->tls_cafile){ _mosquitto_free(mosq->tls_cafile); mosq->tls_cafile = NULL; } if(mosq->tls_capath){ _mosquitto_free(mosq->tls_capath); mosq->tls_capath = NULL; } if(mosq->tls_certfile){ _mosquitto_free(mosq->tls_certfile); mosq->tls_certfile = NULL; } return MOSQ_ERR_INVAL; } mosq->tls_keyfile = _mosquitto_strdup(keyfile); if(!mosq->tls_keyfile){ return MOSQ_ERR_NOMEM; } }else{ if(mosq->tls_keyfile) _mosquitto_free(mosq->tls_keyfile); mosq->tls_keyfile = NULL; } mosq->tls_pw_callback = pw_callback; return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif }
int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain) { struct mosquitto_message_all *message; uint16_t local_mid; int queue_status; if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL; if(STREMPTY(topic)) return MOSQ_ERR_INVAL; if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ return MOSQ_ERR_INVAL; } local_mid = _mosquitto_mid_generate(mosq); if(mid){ *mid = local_mid; } if(qos == 0){ return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false); }else{ message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); if(!message) return MOSQ_ERR_NOMEM; message->next = NULL; message->timestamp = mosquitto_time(); message->msg.mid = local_mid; message->msg.topic = _mosquitto_strdup(topic); if(!message->msg.topic){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } if(payloadlen){ message->msg.payloadlen = payloadlen; message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t)); if(!message->msg.payload){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); }else{ message->msg.payloadlen = 0; message->msg.payload = NULL; } message->msg.qos = qos; message->msg.retain = retain; message->dup = false; pthread_mutex_lock(&mosq->out_message_mutex); printf("================ mosquitto.c ================\n"); printf("#mosq->inflight_messages : %s\n", mosq->inflight_messages); queue_status = _mosquitto_message_queue(mosq, message, mosq_md_out); if(queue_status == 0){ if(qos == 1){ message->state = mosq_ms_wait_for_puback; }else if(qos == 2){ message->state = mosq_ms_wait_for_pubrec; } pthread_mutex_unlock(&mosq->out_message_mutex); return _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); }else{ message->state = mosq_ms_invalid; pthread_mutex_unlock(&mosq->out_message_mutex); return MOSQ_ERR_SUCCESS; } } }
int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context) { char *protocol_name = NULL; uint8_t protocol_version; uint8_t connect_flags; char *client_id = NULL; char *will_payload = NULL, *will_topic = NULL; uint16_t will_payloadlen; struct mosquitto_message *will_struct = NULL; uint8_t will, will_retain, will_qos, clean_session; uint8_t username_flag, password_flag; char *username = NULL, *password = NULL; int i; int rc; struct _mosquitto_acl_user *acl_tail; int slen; #ifdef WITH_TLS X509 *client_cert; X509_NAME *name; X509_NAME_ENTRY *name_entry; #endif struct _clientid_index_hash *find_cih; struct _clientid_index_hash *new_cih; #ifdef WITH_SYS_TREE g_connection_count++; #endif /* Don't accept multiple CONNECT commands. */ if(context->state != mosq_cs_new){ mqtt3_context_disconnect(db, context); return MOSQ_ERR_PROTOCOL; } if(_mosquitto_read_string(&context->in_packet, &protocol_name)){ mqtt3_context_disconnect(db, context); return 1; } if(!protocol_name){ mqtt3_context_disconnect(db, context); return 3; } if(strcmp(protocol_name, PROTOCOL_NAME)){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol \"%s\" in CONNECT from %s.", protocol_name, context->address); } _mosquitto_free(protocol_name); mqtt3_context_disconnect(db, context); return MOSQ_ERR_PROTOCOL; } _mosquitto_free(protocol_name); if(_mosquitto_read_byte(&context->in_packet, &protocol_version)){ mqtt3_context_disconnect(db, context); return 1; } if((protocol_version&0x7F) != PROTOCOL_VERSION){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.", protocol_version, context->address); } _mosquitto_send_connack(context, CONNACK_REFUSED_PROTOCOL_VERSION); mqtt3_context_disconnect(db, context); return MOSQ_ERR_PROTOCOL; } if((protocol_version&0x80) == 0x80){ context->is_bridge = true; } if(_mosquitto_read_byte(&context->in_packet, &connect_flags)){ mqtt3_context_disconnect(db, context); return 1; } clean_session = connect_flags & 0x02; will = connect_flags & 0x04; will_qos = (connect_flags & 0x18) >> 3; will_retain = connect_flags & 0x20; password_flag = connect_flags & 0x40; username_flag = connect_flags & 0x80; if(_mosquitto_read_uint16(&context->in_packet, &(context->keepalive))){ mqtt3_context_disconnect(db, context); return 1; } if(_mosquitto_read_string(&context->in_packet, &client_id)){ mqtt3_context_disconnect(db, context); return 1; } slen = strlen(client_id); #ifdef WITH_STRICT_PROTOCOL if(slen > 23 || slen == 0){ #else if(slen == 0){ #endif _mosquitto_free(client_id); _mosquitto_send_connack(context, CONNACK_REFUSED_IDENTIFIER_REJECTED); mqtt3_context_disconnect(db, context); return 1; } /* clientid_prefixes check */ if(db->config->clientid_prefixes){ if(strncmp(db->config->clientid_prefixes, client_id, strlen(db->config->clientid_prefixes))){ _mosquitto_free(client_id); _mosquitto_send_connack(context, CONNACK_REFUSED_NOT_AUTHORIZED); mqtt3_context_disconnect(db, context); return MOSQ_ERR_SUCCESS; } } if(will){ will_struct = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); if(!will_struct){ mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } if(_mosquitto_read_string(&context->in_packet, &will_topic)){ mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; } if(strlen(will_topic) == 0){ /* FIXME - CONNACK_REFUSED_IDENTIFIER_REJECTED not really appropriate here. */ _mosquitto_send_connack(context, CONNACK_REFUSED_IDENTIFIER_REJECTED); mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; } if(_mosquitto_read_uint16(&context->in_packet, &will_payloadlen)){ mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; } if(will_payloadlen > 0){ will_payload = _mosquitto_malloc(will_payloadlen); if(!will_payload){ mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; } rc = _mosquitto_read_bytes(&context->in_packet, will_payload, will_payloadlen); if(rc){ mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; } } } if(username_flag){ rc = _mosquitto_read_string(&context->in_packet, &username); if(rc == MOSQ_ERR_SUCCESS){ if(password_flag){ rc = _mosquitto_read_string(&context->in_packet, &password); if(rc == MOSQ_ERR_NOMEM){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; }else if(rc == MOSQ_ERR_PROTOCOL){ /* Password flag given, but no password. Ignore. */ password_flag = 0; } } }else if(rc == MOSQ_ERR_NOMEM){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; }else{ /* Username flag given, but no username. Ignore. */ username_flag = 0; } } #ifdef WITH_TLS if(context->listener->use_identity_as_username){ if(!context->ssl){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } #ifdef REAL_WITH_TLS_PSK if(context->listener->psk_hint){ /* Client should have provided an identity to get this far. */ if(!context->username){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } }else{ #endif /* REAL_WITH_TLS_PSK */ client_cert = SSL_get_peer_certificate(context->ssl); if(!client_cert){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } name = X509_get_subject_name(client_cert); if(!name){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); if(i == -1){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } name_entry = X509_NAME_get_entry(name, i); context->username = _mosquitto_strdup((char *)ASN1_STRING_data(name_entry->value)); if(!context->username){ rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } #ifdef REAL_WITH_TLS_PSK } #endif /* REAL_WITH_TLS_PSK */ }else{ #endif /* WITH_TLS */ if(username_flag){ rc = mosquitto_unpwd_check(db, username, password); if(rc == MOSQ_ERR_AUTH){ _mosquitto_send_connack(context, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; }else if(rc == MOSQ_ERR_INVAL){ goto handle_connect_error; } context->username = username; context->password = password; username = NULL; /* Avoid free() in error: below. */ password = NULL; } if(!username_flag && db->config->allow_anonymous == false){ _mosquitto_send_connack(context, CONNACK_REFUSED_NOT_AUTHORIZED); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } #ifdef WITH_TLS } #endif /* Find if this client already has an entry. This must be done *after* any security checks. */ HASH_FIND_STR(db->clientid_index_hash, client_id, find_cih); if(find_cih){ i = find_cih->db_context_index; /* Found a matching client */ if(db->contexts[i]->sock == -1){ /* Client is reconnecting after a disconnect */ /* FIXME - does anything else need to be done here? */ }else{ /* Client is already connected, disconnect old version */ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Client %s already connected, closing old connection.", client_id); } } db->contexts[i]->clean_session = clean_session; mqtt3_context_cleanup(db, db->contexts[i], false); db->contexts[i]->state = mosq_cs_connected; db->contexts[i]->address = _mosquitto_strdup(context->address); db->contexts[i]->sock = context->sock; db->contexts[i]->listener = context->listener; db->contexts[i]->last_msg_in = mosquitto_time(); db->contexts[i]->last_msg_out = mosquitto_time(); db->contexts[i]->keepalive = context->keepalive; db->contexts[i]->pollfd_index = context->pollfd_index; #ifdef WITH_TLS db->contexts[i]->ssl = context->ssl; #endif if(context->username){ db->contexts[i]->username = _mosquitto_strdup(context->username); } context->sock = -1; #ifdef WITH_TLS context->ssl = NULL; #endif context->state = mosq_cs_disconnecting; context = db->contexts[i]; if(context->msgs){ mqtt3_db_message_reconnect_reset(context); } } context->id = client_id; client_id = NULL; context->clean_session = clean_session; context->ping_t = 0; // Add the client ID to the DB hash table here new_cih = _mosquitto_malloc(sizeof(struct _clientid_index_hash)); if(!new_cih){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } new_cih->id = context->id; new_cih->db_context_index = context->db_index; HASH_ADD_KEYPTR(hh, db->clientid_index_hash, context->id, strlen(context->id), new_cih); #ifdef WITH_PERSISTENCE if(!clean_session){ db->persistence_changes++; } #endif /* Associate user with its ACL, assuming we have ACLs loaded. */ if(db->acl_list){ acl_tail = db->acl_list; while(acl_tail){ if(context->username){ if(acl_tail->username && !strcmp(context->username, acl_tail->username)){ context->acl_list = acl_tail; break; } }else{ if(acl_tail->username == NULL){ context->acl_list = acl_tail; break; } } acl_tail = acl_tail->next; } }else{ context->acl_list = NULL; } if(will_struct){ if(mosquitto_acl_check(db, context, will_topic, MOSQ_ACL_WRITE) != MOSQ_ERR_SUCCESS){ _mosquitto_send_connack(context, CONNACK_REFUSED_NOT_AUTHORIZED); mqtt3_context_disconnect(db, context); rc = MOSQ_ERR_SUCCESS; goto handle_connect_error; } context->will = will_struct; context->will->topic = will_topic; if(will_payload){ context->will->payload = will_payload; context->will->payloadlen = will_payloadlen; }else{ context->will->payload = NULL; context->will->payloadlen = 0; } context->will->qos = will_qos; context->will->retain = will_retain; } if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s as %s (c%d, k%d).", context->address, context->id, context->clean_session, context->keepalive); } context->state = mosq_cs_connected; return _mosquitto_send_connack(context, CONNACK_ACCEPTED); handle_connect_error: if(client_id) _mosquitto_free(client_id); if(username) _mosquitto_free(username); if(password) _mosquitto_free(password); if(will_payload) _mosquitto_free(will_payload); if(will_topic) _mosquitto_free(will_topic); if(will_struct) _mosquitto_free(will_struct); return rc; } int mqtt3_handle_disconnect(struct mosquitto_db *db, struct mosquitto *context) { if(!context){ return MOSQ_ERR_INVAL; } if(context->in_packet.remaining_length != 0){ return MOSQ_ERR_PROTOCOL; } _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received DISCONNECT from %s", context->id); context->state = mosq_cs_disconnecting; mqtt3_context_disconnect(db, context); return MOSQ_ERR_SUCCESS; } int mqtt3_handle_subscribe(struct mosquitto_db *db, struct mosquitto *context) { int rc = 0; int rc2; uint16_t mid; char *sub; uint8_t qos; uint8_t *payload = NULL, *tmp_payload; uint32_t payloadlen = 0; int len; char *sub_mount; if(!context) return MOSQ_ERR_INVAL; _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBSCRIBE from %s", context->id); /* FIXME - plenty of potential for memory leaks here */ if(_mosquitto_read_uint16(&context->in_packet, &mid)) return 1; while(context->in_packet.pos < context->in_packet.remaining_length){ sub = NULL; if(_mosquitto_read_string(&context->in_packet, &sub)){ if(payload) _mosquitto_free(payload); return 1; } if(sub){ if(_mosquitto_read_byte(&context->in_packet, &qos)){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(qos > 2){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid QoS in subscription command from %s, disconnecting.", context->address); _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(_mosquitto_fix_sub_topic(&sub)){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(!strlen(sub)){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Empty subscription string from %s, disconnecting.", context->address); _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(context->listener && context->listener->mount_point){ len = strlen(context->listener->mount_point) + strlen(sub) + 1; sub_mount = _mosquitto_calloc(len, sizeof(char)); if(!sub_mount){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return MOSQ_ERR_NOMEM; } snprintf(sub_mount, len, "%s%s", context->listener->mount_point, sub); _mosquitto_free(sub); sub = sub_mount; } _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "\t%s (QoS %d)", sub, qos); rc2 = mqtt3_sub_add(db, context, sub, qos, &db->subs); if(rc2 == MOSQ_ERR_SUCCESS){ if(mqtt3_retain_queue(db, context, sub, qos)) rc = 1; }else if(rc2 != -1){ rc = rc2; } _mosquitto_log_printf(NULL, MOSQ_LOG_SUBSCRIBE, "%s %d %s", context->id, qos, sub); _mosquitto_free(sub); tmp_payload = _mosquitto_realloc(payload, payloadlen + 1); if(tmp_payload){ payload = tmp_payload; payload[payloadlen] = qos; payloadlen++; }else{ if(payload) _mosquitto_free(payload); return MOSQ_ERR_NOMEM; } } } if(_mosquitto_send_suback(context, mid, payloadlen, payload)) rc = 1; _mosquitto_free(payload); #ifdef WITH_PERSISTENCE db->persistence_changes++; #endif return rc; }
int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *userdata) { int i; if(!mosq) return MOSQ_ERR_INVAL; if(clean_session == false && id == NULL){ return MOSQ_ERR_INVAL; } _mosquitto_destroy(mosq); memset(mosq, 0, sizeof(struct mosquitto)); if(userdata){ mosq->userdata = userdata; }else{ mosq->userdata = mosq; } mosq->protocol = mosq_p_mqtt31; mosq->sock = INVALID_SOCKET; mosq->sockpairR = INVALID_SOCKET; mosq->sockpairW = INVALID_SOCKET; mosq->keepalive = 60; mosq->message_retry = 20; mosq->last_retry_check = 0; mosq->clean_session = clean_session; if(id){ if(STREMPTY(id)){ return MOSQ_ERR_INVAL; } mosq->id = _mosquitto_strdup(id); }else{ mosq->id = (char *)_mosquitto_calloc(24, sizeof(char)); if(!mosq->id){ return MOSQ_ERR_NOMEM; } mosq->id[0] = 'm'; mosq->id[1] = 'o'; mosq->id[2] = 's'; mosq->id[3] = 'q'; mosq->id[4] = '/'; for(i=5; i<23; i++){ mosq->id[i] = (rand()%73)+48; } } mosq->in_packet.payload = NULL; _mosquitto_packet_cleanup(&mosq->in_packet); mosq->out_packet = NULL; mosq->current_out_packet = NULL; mosq->last_msg_in = mosquitto_time(); mosq->last_msg_out = mosquitto_time(); mosq->ping_t = 0; mosq->last_mid = 0; mosq->state = mosq_cs_new; mosq->in_messages = NULL; mosq->in_messages_last = NULL; mosq->out_messages = NULL; mosq->out_messages_last = NULL; mosq->max_inflight_messages = 20; mosq->will = NULL; mosq->on_connect = NULL; mosq->on_publish = NULL; mosq->on_message = NULL; mosq->on_subscribe = NULL; mosq->on_unsubscribe = NULL; mosq->host = NULL; mosq->port = 1883; mosq->in_callback = false; mosq->in_queue_len = 0; mosq->out_queue_len = 0; mosq->reconnect_delay = 1; mosq->reconnect_delay_max = 1; mosq->reconnect_exponential_backoff = false; mosq->threaded = false; #ifdef WITH_TLS mosq->ssl = NULL; mosq->tls_cert_reqs = SSL_VERIFY_PEER; mosq->tls_insecure = false; mosq->want_write = false; #endif #ifdef WITH_THREADING pthread_mutex_init(&mosq->exe_mutex, NULL); pthread_mutex_init(&mosq->callback_mutex, NULL); pthread_mutex_init(&mosq->log_callback_mutex, NULL); pthread_mutex_init(&mosq->state_mutex, NULL); pthread_mutex_init(&mosq->out_packet_mutex, NULL); pthread_mutex_init(&mosq->current_out_packet_mutex, NULL); pthread_mutex_init(&mosq->msgtime_mutex, NULL); pthread_mutex_init(&mosq->in_message_mutex, NULL); pthread_mutex_init(&mosq->out_message_mutex, NULL); pthread_mutex_init(&mosq->mid_mutex, NULL); mosq->thread_id = pthread_self(); #endif return MOSQ_ERR_SUCCESS; }
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_handle_connect(struct mosquitto_db *db, struct mosquitto *context) { char *protocol_name = NULL; uint8_t protocol_version; uint8_t connect_flags; uint8_t connect_ack = 0; char *client_id = NULL; char *will_payload = NULL, *will_topic = NULL; char *will_topic_mount; uint16_t will_payloadlen; struct mosquitto_message *will_struct = NULL; uint8_t will, will_retain, will_qos, clean_session; uint8_t username_flag, password_flag; char *username = NULL, *password = NULL; int rc; struct _mosquitto_acl_user *acl_tail; struct mosquitto_client_msg *msg_tail, *msg_prev; struct mosquitto *found_context; int slen; struct _mosquitto_subleaf *leaf; int i; #ifdef WITH_TLS X509 *client_cert = NULL; X509_NAME *name; X509_NAME_ENTRY *name_entry; #endif #ifdef WITH_SYS_TREE g_connection_count++; #endif g_epoll_mqtt_connections++; /* Don't accept multiple CONNECT commands. */ if(context->state != mosq_cs_new){ rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } if(_mosquitto_read_string(&context->in_packet, &protocol_name)){ rc = 1; goto handle_connect_error; return 1; } if(!protocol_name){ rc = 3; goto handle_connect_error; return 3; } if(_mosquitto_read_byte(&context->in_packet, &protocol_version)){ rc = 1; goto handle_connect_error; return 1; } if(!strcmp(protocol_name, PROTOCOL_NAME_v31)){ if((protocol_version&0x7F) != PROTOCOL_VERSION_v31){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.", protocol_version, context->address); } _mosquitto_send_connack(context, 0, CONNACK_REFUSED_PROTOCOL_VERSION); _mosquitto_free(protocol_name); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } context->protocol = mosq_p_mqtt31; }else if(!strcmp(protocol_name, PROTOCOL_NAME_v311)){ if((protocol_version&0x7F) != PROTOCOL_VERSION_v311){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.", protocol_version, context->address); } _mosquitto_send_connack(context, 0, CONNACK_REFUSED_PROTOCOL_VERSION); _mosquitto_free(protocol_name); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } if((context->in_packet.command&0x0F) != 0x00){ /* Reserved flags not set to 0, must disconnect. */ _mosquitto_free(protocol_name); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } context->protocol = mosq_p_mqtt311; }else{ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol \"%s\" in CONNECT from %s.", protocol_name, context->address); } _mosquitto_free(protocol_name); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } _mosquitto_free(protocol_name); if(_mosquitto_read_byte(&context->in_packet, &connect_flags)){ rc = 1; goto handle_connect_error; } clean_session = (connect_flags & 0x02) >> 1; will = connect_flags & 0x04; will_qos = (connect_flags & 0x18) >> 3; if(will_qos == 3){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid Will QoS in CONNECT from %s.", context->address); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } will_retain = connect_flags & 0x20; password_flag = connect_flags & 0x40; username_flag = connect_flags & 0x80; if(_mosquitto_read_uint16(&context->in_packet, &(context->keepalive))){ rc = 1; goto handle_connect_error; } if(_mosquitto_read_string(&context->in_packet, &client_id)){ rc = 1; goto handle_connect_error; } slen = strlen(client_id); if(slen == 0){ if(context->protocol == mosq_p_mqtt31){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_IDENTIFIER_REJECTED); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; }else{ /* mqtt311 */ _mosquitto_free(client_id); client_id = NULL; if(clean_session == 0 || db->config->allow_zero_length_clientid == false){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_IDENTIFIER_REJECTED); rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; }else{ client_id = client_id_gen(db); if(!client_id){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } } } } /* clientid_prefixes check */ if(db->config->clientid_prefixes){ if(strncmp(db->config->clientid_prefixes, client_id, strlen(db->config->clientid_prefixes))){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED); rc = 1; goto handle_connect_error; } } if(will){ will_struct = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); if(!will_struct){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } if(_mosquitto_read_string(&context->in_packet, &will_topic)){ rc = 1; goto handle_connect_error; } if(STREMPTY(will_topic)){ rc = 1; goto handle_connect_error; } if(context->listener && context->listener->mount_point){ slen = strlen(context->listener->mount_point) + strlen(will_topic); will_topic_mount = _mosquitto_malloc(slen+1); if(!will_topic_mount){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } snprintf(will_topic_mount, slen, "%s%s", context->listener->mount_point, will_topic); will_topic_mount[slen] = '\0'; _mosquitto_free(will_topic); will_topic = will_topic_mount; } if(mosquitto_pub_topic_check(will_topic)){ rc = 1; goto handle_connect_error; } if(_mosquitto_read_uint16(&context->in_packet, &will_payloadlen)){ rc = 1; goto handle_connect_error; } if(will_payloadlen > 0){ will_payload = _mosquitto_malloc(will_payloadlen); if(!will_payload){ rc = 1; goto handle_connect_error; } rc = _mosquitto_read_bytes(&context->in_packet, will_payload, will_payloadlen); if(rc){ rc = 1; goto handle_connect_error; } } }else{ if(context->protocol == mosq_p_mqtt311){ if(will_qos != 0 || will_retain != 0){ rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } } } if(username_flag){ rc = _mosquitto_read_string(&context->in_packet, &username); if(rc == MOSQ_ERR_SUCCESS){ if(password_flag){ rc = _mosquitto_read_string(&context->in_packet, &password); if(rc == MOSQ_ERR_NOMEM){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; }else if(rc == MOSQ_ERR_PROTOCOL){ if(context->protocol == mosq_p_mqtt31){ /* Password flag given, but no password. Ignore. */ password_flag = 0; }else if(context->protocol == mosq_p_mqtt311){ rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } } } }else if(rc == MOSQ_ERR_NOMEM){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; }else{ if(context->protocol == mosq_p_mqtt31){ /* Username flag given, but no username. Ignore. */ username_flag = 0; }else if(context->protocol == mosq_p_mqtt311){ rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } } }else{ if(context->protocol == mosq_p_mqtt311){ if(password_flag){ /* username_flag == 0 && password_flag == 1 is forbidden */ rc = MOSQ_ERR_PROTOCOL; goto handle_connect_error; } } } #ifdef WITH_TLS if(context->listener && context->listener->ssl_ctx && context->listener->use_identity_as_username){ if(!context->ssl){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); rc = 1; goto handle_connect_error; } #ifdef REAL_WITH_TLS_PSK if(context->listener->psk_hint){ /* Client should have provided an identity to get this far. */ if(!context->username){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); rc = 1; goto handle_connect_error; } }else{ #endif /* REAL_WITH_TLS_PSK */ client_cert = SSL_get_peer_certificate(context->ssl); if(!client_cert){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); rc = 1; goto handle_connect_error; } name = X509_get_subject_name(client_cert); if(!name){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); rc = 1; goto handle_connect_error; } i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); if(i == -1){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD); rc = 1; goto handle_connect_error; } name_entry = X509_NAME_get_entry(name, i); context->username = _mosquitto_strdup((char *)ASN1_STRING_data(name_entry->value)); if(!context->username){ rc = 1; goto handle_connect_error; } X509_free(client_cert); client_cert = NULL; #ifdef REAL_WITH_TLS_PSK } #endif /* REAL_WITH_TLS_PSK */ }else{ #endif /* WITH_TLS */ if(username_flag){ rc = mosquitto_unpwd_check(db, username, password); switch(rc){ case MOSQ_ERR_SUCCESS: break; case MOSQ_ERR_AUTH: _mosquitto_send_connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED); mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; break; default: mqtt3_context_disconnect(db, context); rc = 1; goto handle_connect_error; break; } context->username = username; context->password = password; username = NULL; /* Avoid free() in error: below. */ password = NULL; } if(!username_flag && db->config->allow_anonymous == false){ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED); rc = 1; goto handle_connect_error; } #ifdef WITH_TLS } #endif if(context->listener && context->listener->use_username_as_clientid){ if(context->username){ _mosquitto_free(client_id); client_id = _mosquitto_strdup(context->username); if(!client_id){ rc = MOSQ_ERR_NOMEM; goto handle_connect_error; } }else{ _mosquitto_send_connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED); rc = 1; goto handle_connect_error; } } /* Find if this client already has an entry. This must be done *after* any security checks. */ HASH_FIND(hh_id, db->contexts_by_id, client_id, strlen(client_id), found_context); if(found_context){ /* Found a matching client */ if(found_context->sock == INVALID_SOCKET){ /* Client is reconnecting after a disconnect */ /* FIXME - does anything need to be done here? */ }else{ /* Client is already connected, disconnect old version. This is * done in mqtt3_context_cleanup() below. */ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Client %s already connected, closing old connection.", client_id); } } if(context->protocol == mosq_p_mqtt311){ if(clean_session == 0){ connect_ack |= 0x01; } } context->clean_session = clean_session; if(context->clean_session == false && found_context->clean_session == false){ if(found_context->msgs){ context->msgs = found_context->msgs; found_context->msgs = NULL; mqtt3_db_message_reconnect_reset(db, context); } context->subs = found_context->subs; found_context->subs = NULL; context->sub_count = found_context->sub_count; found_context->sub_count = 0; for(i=0; i<context->sub_count; i++){ if(context->subs[i]){ leaf = context->subs[i]->subs; while(leaf){ if(leaf->context == found_context){ leaf->context = context; } leaf = leaf->next; } } } } found_context->clean_session = true; found_context->state = mosq_cs_disconnecting; if(g_flag_epoll) { epoll_do_disconnect(db,found_context); } else { do_disconnect(db, found_context); } } /* Associate user with its ACL, assuming we have ACLs loaded. */ if(db->acl_list){ acl_tail = db->acl_list; while(acl_tail){ if(context->username){ if(acl_tail->username && !strcmp(context->username, acl_tail->username)){ context->acl_list = acl_tail; break; } }else{ if(acl_tail->username == NULL){ context->acl_list = acl_tail; break; } } acl_tail = acl_tail->next; } }else{ context->acl_list = NULL; } if(will_struct){ context->will = will_struct; context->will->topic = will_topic; if(will_payload){ context->will->payload = will_payload; context->will->payloadlen = will_payloadlen; }else{ context->will->payload = NULL; context->will->payloadlen = 0; } context->will->qos = will_qos; context->will->retain = will_retain; } if(db->config->connection_messages == true){ if(context->is_bridge){ if(context->username){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New bridge connected from %s as %s (c%d, k%d, u'%s').", context->address, client_id, clean_session, context->keepalive, context->username); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New bridge connected from %s as %s (c%d, k%d).", context->address, client_id, clean_session, context->keepalive); } }else{ if(context->username){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s as %s (c%d, k%d, u'%s').", context->address, client_id, clean_session, context->keepalive, context->username); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s as %s (c%d, k%d).", context->address, client_id, clean_session, context->keepalive); } } } context->id = client_id; client_id = NULL; context->clean_session = clean_session; context->ping_t = 0; context->is_dropping = false; if((protocol_version&0x80) == 0x80){ context->is_bridge = true; } /* Remove any queued messages that are no longer allowed through ACL, * assuming a possible change of username. */ msg_tail = context->msgs; msg_prev = NULL; while(msg_tail){ if(msg_tail->direction == mosq_md_out){ if(mosquitto_acl_check(db, context, msg_tail->store->topic, MOSQ_ACL_READ) != MOSQ_ERR_SUCCESS){ mosquitto__db_msg_store_deref(db, &msg_tail->store); if(msg_prev){ msg_prev->next = msg_tail->next; _mosquitto_free(msg_tail); msg_tail = msg_prev->next; }else{ context->msgs = context->msgs->next; _mosquitto_free(msg_tail); msg_tail = context->msgs; } }else{ msg_prev = msg_tail; msg_tail = msg_tail->next; } }else{ msg_prev = msg_tail; msg_tail = msg_tail->next; } } HASH_ADD_KEYPTR(hh_id, db->contexts_by_id, context->id, strlen(context->id), context); #ifdef WITH_PERSISTENCE if(!clean_session){ db->persistence_changes++; } #endif context->state = mosq_cs_connected; return _mosquitto_send_connack(context, connect_ack, CONNACK_ACCEPTED); handle_connect_error: if(client_id) _mosquitto_free(client_id); if(username) _mosquitto_free(username); if(password) _mosquitto_free(password); if(will_payload) _mosquitto_free(will_payload); if(will_topic) _mosquitto_free(will_topic); if(will_struct) _mosquitto_free(will_struct); #ifdef WITH_TLS if(client_cert) X509_free(client_cert); #endif /* We return an error here which means the client is freed later on. */ return rc; }
int _mosquitto_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 _mqtt3_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); cur_topic->remote_prefix[len] = '\0'; _mosquitto_free(mapped_topic); mapped_topic = topic_temp; } _mosquitto_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); #ifdef WITH_SYS_TREE g_pub_bytes_sent += payloadlen; #endif rc = _mosquitto_send_real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup); _mosquitto_free(mapped_topic); return rc; } } } } #endif _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes)) payload is %s", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen, payload); # ifdef WITH_SYS_TREE g_pub_bytes_sent += payloadlen; # endif #else _mosquitto_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 _mosquitto_send_real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup); }