Exemple #1
0
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
{
	struct mosq_config *cfg;
	int i;
	bool res;

	if(process_messages == false) return;

	assert(obj);
	cfg = (struct mosq_config *)obj;

	if(cfg->retained_only && !message->retain && process_messages){
		process_messages = false;
		mosquitto_disconnect(mosq);
		return;
	}

	if(message->retain && cfg->no_retain) return;
	if(cfg->filter_outs){
		for(i=0; i<cfg->filter_out_count; i++){
			mosquitto_topic_matches_sub(cfg->filter_outs[i], message->topic, &res);
			if(res) return;
		}
	}

	print_message(cfg, message);

	if(cfg->msg_count>0){
		msg_count++;
		if(cfg->msg_count == msg_count){
			process_messages = false;
			mosquitto_disconnect(mosq);
		}
	}
}
assert_not_subscribed(const char *topic, const char *subscription)
{
    bool result = true;

    TEST_ASSERT_EQUAL(MOSQ_ERR_SUCCESS,
                      mosquitto_topic_matches_sub(subscription, topic, &result));
    TEST_ASSERT_FALSE(result);
}
int topic_matches_sub(lua_State *lua)
{
    const char *sub = luaL_checkstring(lua, -2);
    const char *topic = luaL_checkstring(lua, -1);

    bool result;
    mosquitto_topic_matches_sub(sub, topic, &result);
    lua_pushboolean(lua, result);
    return 1;
}
int main(int argc, char *argv[])
{
	bool match;

	mosquitto_topic_matches_sub("foo/bar", "foo/bar", &match); if(!match) return 1;
	mosquitto_topic_matches_sub("foo/+", "foo/bar", &match); if(!match) return 1;
	mosquitto_topic_matches_sub("foo/+/baz", "foo/bar/baz", &match); if(!match) return 1;

	mosquitto_topic_matches_sub("foo/+/#", "foo/bar/baz", &match); if(!match) return 1;
	mosquitto_topic_matches_sub("#", "foo/bar/baz", &match); if(!match) return 1;

	mosquitto_topic_matches_sub("foo/bar", "foo", &match); if(match) return 1;
	mosquitto_topic_matches_sub("foo/+", "foo/bar/baz", &match); if(match) return 1;
	mosquitto_topic_matches_sub("foo/+/baz", "foo/bar/bar", &match); if(match) return 1;

	mosquitto_topic_matches_sub("foo/+/#", "fo2/bar/baz", &match); if(match) return 1;

	return 0;
}
Exemple #5
0
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
{
	struct mosq_config *cfg;
	int i;
	bool res;

	if(process_messages == false) return;

	assert(obj);
	cfg = (struct mosq_config *)obj;

	if(message->retain && cfg->no_retain) return;
	if(cfg->filter_outs){
		for(i=0; i<cfg->filter_out_count; i++){
			mosquitto_topic_matches_sub(cfg->filter_outs[i], message->topic, &res);
			if(res) return;
		}
	}

	if(cfg->verbose){
		if(message->payloadlen){
			printf("%s ", message->topic);
			fwrite(message->payload, 1, message->payloadlen, stdout);
			if(cfg->eol){
				printf("\n");
			}
		}else{
			if(cfg->eol){
				printf("%s (null)\n", message->topic);
			}
		}
		fflush(stdout);
	}else{
		if(message->payloadlen){
			fwrite(message->payload, 1, message->payloadlen, stdout);
			if(cfg->eol){
				printf("\n");
			}
			fflush(stdout);
		}
	}
	if(cfg->msg_count>0){
		msg_count++;
		if(cfg->msg_count == msg_count){
			process_messages = false;
			mosquitto_disconnect(mosq);
		}
	}
}
Subscription *
subscription_get(Subscriptions *subscribers, const char *topic)
{
	if (subscribers->first)
	{
		Subscription *sub;
		for (sub = subscribers->first; sub != NULL; sub = sub->next)
		{
			bool result;
			mosquitto_topic_matches_sub(sub->topic, topic, &result);
			if (result)
				return sub;
		}
	}
	return NULL;
}
/* {{{ Mosquitto\Message::topicMatchesSub() */
PHP_METHOD(Mosquitto_Message, topicMatchesSub)
{
	char *topic = NULL, *subscription = NULL;
	int topic_len, subscription_len;
	zend_bool result;

	PHP_MOSQUITTO_ERROR_HANDLING();
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
				&topic, &topic_len, &subscription, &subscription_len) == FAILURE) {
		PHP_MOSQUITTO_RESTORE_ERRORS();
		return;
	}
	PHP_MOSQUITTO_RESTORE_ERRORS();

	mosquitto_topic_matches_sub(subscription, topic, (bool *) &result);
	RETURN_BOOL(result);
}
// Check an embedded document of the form { "article/#": "r", "article/+/comments": "rw", "ballotbox": "w" }
bool be_mongo_check_acl_topics_map(const bson_iter_t *topics, const char *req_topic, int req_access, const char *clientid, const char *username)
{
	bson_iter_t iter;
	bson_iter_recurse(topics, &iter);
	bool granted = false;

	// Loop through mapped topics, allowing for the fact that a two different ACLs may have complementary permissions.
	while (bson_iter_next(&iter) && !granted) {
		const char *permitted_topic = bson_iter_key(&iter);
		bool topic_matches = false;

		char *expanded;

		t_expand(clientid, username, permitted_topic, &expanded);
		if (expanded && *expanded) {
			mosquitto_topic_matches_sub(expanded, req_topic, &topic_matches);
			free(expanded);

			if (topic_matches) {
				bson_type_t val_type = bson_iter_type(&iter);
				if (val_type == BSON_TYPE_UTF8) {
					// NOTE: can req_access be any other value than 1 or 2?
					// in that case this may not be correct:
					// e.g. req_access == 3 (rw) -> granted = (3 & 1 > 0) == true
					const char *permission = bson_iter_utf8(&iter, NULL);
					if (strcmp(permission, "r") == 0) {
						granted = (req_access & 1) > 0;
					} else if (strcmp(permission, "w") == 0) {
						granted = (req_access & 2) > 0;
					} else if (strcmp(permission, "rw") == 0) {
						granted = true;
					}
				}
			}
		}
	}
	return granted;
}
// Check an embedded array of the form [ "public/#", "private/myid/#" ]
bool be_mongo_check_acl_topics_array(const bson_iter_t *topics, const char *req_topic, const char *clientid, const char *username)
{
	bson_iter_t iter;
	bson_iter_recurse(topics, &iter);

	while (bson_iter_next(&iter)) {
		const char *permitted_topic = bson_iter_utf8(&iter, NULL);
		bool topic_matches = false;

		char *expanded;

		t_expand(clientid, username, permitted_topic, &expanded);
		if (expanded && *expanded) {
			mosquitto_topic_matches_sub(expanded, req_topic, &topic_matches);
			free(expanded);

			if (topic_matches) {
				return true;
			}
		}
	}
	return false;
}
void mqtt_message_callback(struct mosquitto *mosq, 
                           void *obj, 
                          const struct mosquitto_message *message)
{
  printf("got message '%.*s' for topic '%s'\n", message->payloadlen, (char*) message->payload, message->topic);

  bool match = false;
  mosquitto_topic_matches_sub(MQTT_DOOR_TOPIC, message->topic, &match);
  if (match) {
    const char* doorstr = message->payload;

    // obtain door status from messages    
    door_is_closed = true;
    door_is_locked = false;
    
    if (!strcmp(doorstr, MQTT_MSG_DOOR_OPEN)) {
      door_is_closed = false;
    }
    
    if (!strcmp(doorstr, MQTT_MSG_DOOR_LOCKED)) {
      door_is_locked = true;
    }    
  }
}
Exemple #11
0
int mqtt3_handle_publish(struct mosquitto_db *db, struct mosquitto *context)
{
	char *topic;
	void *payload = NULL;
	uint32_t payloadlen;
	uint8_t dup, qos, retain;
	uint16_t mid = 0;
	int rc = 0;
	uint8_t header = context->in_packet.command;
	int res = 0;
	struct mosquitto_msg_store *stored = NULL;
	int len;
	char *topic_mount;
#ifdef WITH_BRIDGE
	char *topic_temp;
	int i;
	struct _mqtt3_bridge_topic *cur_topic;
	bool match;
#endif

	dup = (header & 0x08)>>3;
	qos = (header & 0x06)>>1;
	if(qos == 3){
		_mosquitto_log_printf(NULL, MOSQ_LOG_INFO,
				"Invalid QoS in PUBLISH from %s, disconnecting.", context->id);
		return 1;
	}
	retain = (header & 0x01);

	if(_mosquitto_read_string(&context->in_packet, &topic)) return 1;
	if(STREMPTY(topic)){
		/* Invalid publish topic, disconnect client. */
		_mosquitto_free(topic);
		return 1;
	}
#ifdef WITH_BRIDGE
	if(context->bridge && context->bridge->topics && context->bridge->topic_remapping){
		for(i=0; i<context->bridge->topic_count; i++){
			cur_topic = &context->bridge->topics[i];
			if((cur_topic->direction == bd_both || cur_topic->direction == bd_in) 
					&& (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->remote_topic, topic, &match);
				if(rc){
					_mosquitto_free(topic);
					return rc;
				}
				if(match){
					if(cur_topic->remote_prefix){
						/* This prefix needs removing. */
						if(!strncmp(cur_topic->remote_prefix, topic, strlen(cur_topic->remote_prefix))){
							topic_temp = _mosquitto_strdup(topic+strlen(cur_topic->remote_prefix));
							if(!topic_temp){
								_mosquitto_free(topic);
								return MOSQ_ERR_NOMEM;
							}
							_mosquitto_free(topic);
							topic = topic_temp;
						}
					}

					if(cur_topic->local_prefix){
						/* This prefix needs adding. */
						len = strlen(topic) + strlen(cur_topic->local_prefix)+1;
						topic_temp = _mosquitto_malloc(len+1);
						if(!topic_temp){
							_mosquitto_free(topic);
							return MOSQ_ERR_NOMEM;
						}
						snprintf(topic_temp, len, "%s%s", cur_topic->local_prefix, topic);
						topic_temp[len] = '\0';

						_mosquitto_free(topic);
						topic = topic_temp;
					}
					break;
				}
			}
		}
	}
#endif
	if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){
		/* Invalid publish topic, just swallow it. */
		_mosquitto_free(topic);
		return 1;
	}

	if(qos > 0){
		if(_mosquitto_read_uint16(&context->in_packet, &mid)){
			_mosquitto_free(topic);
			return 1;
		}
	}

	payloadlen = context->in_packet.remaining_length - context->in_packet.pos;
#ifdef WITH_SYS_TREE
	g_pub_bytes_received += payloadlen;
#endif
	if(context->listener && context->listener->mount_point){
		len = strlen(context->listener->mount_point) + strlen(topic) + 1;
		topic_mount = _mosquitto_malloc(len+1);
		if(!topic_mount){
			_mosquitto_free(topic);
			return MOSQ_ERR_NOMEM;
		}
		snprintf(topic_mount, len, "%s%s", context->listener->mount_point, topic);
		topic_mount[len] = '\0';

		_mosquitto_free(topic);
		topic = topic_mount;
	}

	if(payloadlen){
		if(db->config->message_size_limit && payloadlen > db->config->message_size_limit){
			_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Dropped too large PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", context->id, dup, qos, retain, mid, topic, (long)payloadlen);
			goto process_bad_message;
		}
		payload = _mosquitto_calloc(payloadlen+1, 1);
		if(!payload){
			_mosquitto_free(topic);
			return 1;
		}
		if(_mosquitto_read_bytes(&context->in_packet, payload, payloadlen)){
			_mosquitto_free(topic);
			_mosquitto_free(payload);
			return 1;
		}
	}

	/* Check for topic access */
	rc = mosquitto_acl_check(db, context, topic, MOSQ_ACL_WRITE);
	if(rc == MOSQ_ERR_ACL_DENIED){
		_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Denied PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", context->id, dup, qos, retain, mid, topic, (long)payloadlen);
		goto process_bad_message;
	}else if(rc != MOSQ_ERR_SUCCESS){
		_mosquitto_free(topic);
		if(payload) _mosquitto_free(payload);
		return rc;
	}

	_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Received PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes) payload %s)", context->id, dup, qos, retain, mid, topic, (long)payloadlen, (char
*)payload);
    
    //Prathamesh
     write(pipeFDS[1],payload, payloadlen);
    
	if(qos > 0){
		mqtt3_db_message_store_find(context, mid, &stored);
	}
	if(!stored){
		dup = 0;
		if(mqtt3_db_message_store(db, context->id, mid, topic, qos, payloadlen, payload, retain, &stored, 0)){
			_mosquitto_free(topic);
			if(payload) _mosquitto_free(payload);
			return 1;
		}
	}else{
		dup = 1;
	}
	switch(qos){
		case 0:
			if(mqtt3_db_messages_queue(db, context->id, topic, qos, retain, &stored)) rc = 1;
			break;
		case 1:
			if(mqtt3_db_messages_queue(db, context->id, topic, qos, retain, &stored)) rc = 1;
			if(_mosquitto_send_puback(context, mid)) rc = 1;
			break;
		case 2:
			if(!dup){
				res = mqtt3_db_message_insert(db, context, mid, mosq_md_in, qos, retain, stored);
			}else{
				res = 0;
			}
			/* mqtt3_db_message_insert() returns 2 to indicate dropped message
			 * due to queue. This isn't an error so don't disconnect them. */
			if(!res){
				if(_mosquitto_send_pubrec(context, mid)) rc = 1;
			}else if(res == 1){
				rc = 1;
			}
			break;
	}
	_mosquitto_free(topic);
	if(payload) _mosquitto_free(payload);

	return rc;
process_bad_message:
	_mosquitto_free(topic);
	if(payload) _mosquitto_free(payload);
	switch(qos){
		case 0:
			return MOSQ_ERR_SUCCESS;
		case 1:
			return _mosquitto_send_puback(context, mid);
		case 2:
			mqtt3_db_message_store_find(context, mid, &stored);
			if(!stored){
				if(mqtt3_db_message_store(db, context->id, mid, NULL, qos, 0, NULL, false, &stored, 0)){
					return 1;
				}
				res = mqtt3_db_message_insert(db, context, mid, mosq_md_in, qos, false, stored);
			}else{
				res = 0;
			}
			if(!res){
				res = _mosquitto_send_pubrec(context, mid);
			}
			return res;
	}
	return 1;
}
int be_pg_aclcheck(void *handle, const char *clientid, const char *username, const char *topic, int acc)
{
	struct pg_backend *conf = (struct pg_backend *)handle;
	char *v = NULL;
	int match = 0;
	bool bf;
	PGresult *res = NULL;

	_log( LOG_DEBUG, "USERNAME: %s, TOPIC: %s, acc: %d", username, topic, acc );


	if (!conf || !conf->aclquery)
		return (FALSE);

	int localacc = htonl(acc);

	const char *values[2] = {username,(char*)&localacc};
	int lengths[2] = {strlen(username),sizeof(localacc)};
	int binary[2] = {0,1};

	res = PQexecParams(conf->conn, conf->aclquery, 2, NULL, values, lengths, binary, 0);

	if ( PQresultStatus(res) != PGRES_TUPLES_OK )
	{
		fprintf(stderr, "%s\n", PQresultErrorMessage(res));
		match = BACKEND_ERROR;
		goto out;
	}

	if (PQnfields(res) != 1) {
		fprintf(stderr, "numfields not ok\n");
		goto out;
	}

	int rec_count = PQntuples(res);
	int row = 0;
	for ( row = 0; row < rec_count; row++ ) {
		if ( (v = PQgetvalue(res,row,0) ) != NULL) {

			/* Check mosquitto_match_topic. If true,
			 * if true, set match and break out of loop. */

                        char *expanded;

                        t_expand(clientid, username, v, &expanded);
                        if (expanded && *expanded) {
                                mosquitto_topic_matches_sub(expanded, topic, &bf);
                                match |= bf;
                                _log(LOG_DEBUG, "  postgres: topic_matches(%s, %s) == %d",
                                        expanded, v, bf);

				free(expanded);
                        }
		}

		if ( match != 0 )
		{
			break;
		}
	}

out:

	PQclear(res);

	return (match);
}
int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, const char *topic, int acc)
{
	struct mongo_backend *handle = (struct mongo_backend *) conf;
	mongoc_collection_t *collection;
	mongoc_cursor_t *cursor;
	bson_error_t error;
	const bson_t *doc;
	bson_iter_t iter;

	bool check = false;
	int match = 0, foundFlag = 0;

	bson_t query;

	bson_init(&query);
	bson_append_utf8(&query, "username", -1, username, -1);

	collection = mongoc_client_get_collection(handle->client, dbName, colName);

	cursor = mongoc_collection_find(collection,
									MONGOC_QUERY_NONE,
									0,
									0,
									0,
									&query,
									NULL,
									NULL);
	
	while (!mongoc_cursor_error (cursor, &error) &&
			mongoc_cursor_more (cursor)) {
		if (foundFlag == 0 && mongoc_cursor_next (cursor, &doc)) {
				bson_iter_init(&iter, doc);
				bson_iter_find(&iter, topicLoc);

				int64_t topId = (int64_t) bson_iter_as_int64(&iter);//, NULL);

				bson_destroy(&query);
				mongoc_cursor_destroy(cursor);
				mongoc_collection_destroy(collection);
				
				bson_init(&query);
				bson_append_int64(&query, topicID, -1, topId);
				collection = mongoc_client_get_collection(handle->client, dbName, topicLoc);
				cursor = mongoc_collection_find(collection,
												MONGOC_QUERY_NONE,
												0,
												0,
												0,
												&query,
												NULL,
												NULL);		
				foundFlag = 1;
		}
		if (foundFlag == 1 && mongoc_cursor_next(cursor, &doc)) {
				
			bson_iter_init(&iter, doc);
			bson_iter_find(&iter, topicLoc);
			uint32_t len;
			const uint8_t *arr;
			bson_iter_array(&iter, &len, &arr);
			bson_t b;
			
			
			
			if (bson_init_static(&b, arr, len))	{
				bson_iter_init(&iter, &b);
				while (bson_iter_next(&iter)) {
			
					char *str = bson_iter_dup_utf8(&iter, &len);

					mosquitto_topic_matches_sub(str, topic, &check);
					if (check) {
							match = 1;
							bson_free(str);
							break;
					}
					bson_free(str);
				}
			}

		}

	}
	

	if (mongoc_cursor_error (cursor, &error)) {
			fprintf (stderr, "Cursor Failure: %s\n", error.message);
			return 0;
	}
	

	bson_destroy(&query);
	mongoc_cursor_destroy (cursor);
	mongoc_collection_destroy(collection);


	



	return match;
}
Exemple #14
0
void my_message_file_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
{
	struct mosq_config *cfg;
	int i;
	bool res;

	if(process_messages == false) return;

	assert(obj);
	cfg = (struct mosq_config *)obj;

	if(cfg->retained_only && !message->retain && process_messages){
		process_messages = false;
		mosquitto_disconnect(mosq);
		return;
	}
    
	if(message->retain && cfg->no_retain) return;
	if(cfg->filter_outs){
		for(i=0; i<cfg->filter_out_count; i++){
			mosquitto_topic_matches_sub(cfg->filter_outs[i], message->topic, &res);
			if(res) return;
		}
	}
	cfg->fmask_topic = message->topic;

	FILE *fptr = NULL;

	_fmask(cfg->fmask, cfg);

	char *path, *prog;
	path = dirname(strdup(cfg->ffmask));
	prog = basename(strdup(cfg->ffmask));
	
	mkpath(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
	
	/* reasonable method to distinguish between directory 
	 * and a writable node (by default is off) */
	if(cfg->nodesuffix) {
		char *sf = cfg->nsuffix;      /* limit 16 bytes. */
		sf = stpcpy(sf, cfg->nodesuffix);
		if(cfg->nsuffix) {
			char *to = cfg->ffmask;
			to = stpcpy(to, path);
			to = stpcpy(to, "/");
			if(prog) {
				to = stpcpy(to, prog);
			}
			to = stpcpy(to, ".");
			to = stpcpy(to, cfg->nsuffix);
		}
	}

	if(cfg->overwrite) {
		fptr = _mosquitto_fopen(cfg->ffmask, "w");
	} else {
		fptr = _mosquitto_fopen(cfg->ffmask, "a");
	}

	if(!fptr){
		fprintf(stderr, "Error: cannot open outfile, using stdout - %s\n", cfg->ffmask);
		// need to do normal stdout
		//mosquitto_message_callback_set(mosq, "my_message_callback");
	} else{
		if(cfg->verbose){
			if(message->payloadlen){
				fprintf(fptr, "%s ", message->topic);
				fwrite(message->payload, 1, message->payloadlen, fptr);
				if(cfg->eol){
					fprintf(fptr, "\n");
				}
			}else{
				if(cfg->eol){
					fprintf(fptr, "%s (null)\n", message->topic);
				}
			}
		}else{
			if(message->payloadlen){
				fwrite(message->payload, 1, message->payloadlen, fptr);
				if(cfg->eol){
					fprintf(fptr, "\n");
				}
			}
		}
		fclose(fptr);
	}
	if(cfg->msg_count>0){
		msg_count++;
		if(cfg->msg_count == msg_count){
			process_messages = false;
			mosquitto_disconnect(mosq);
		}
	}
}
int be_pg_aclcheck(void *handle, const char *clientid, const char *username, const char *topic, int acc)
{
	struct pg_backend *conf = (struct pg_backend *)handle;
	char *v = NULL;
	int match = BACKEND_DEFER;
	bool bf;
	PGresult *res = NULL;

	_log(LOG_DEBUG, "USERNAME: %s, TOPIC: %s, acc: %d", username, topic, acc);


	if (!conf || !conf->aclquery)
		return BACKEND_DEFER;

	const int buflen = 11;
	//10 for 2^32 + 1
	char accbuffer[buflen];
	snprintf(accbuffer, buflen, "%d", acc);

	const char *values[2] = {username, accbuffer};
	int lengths[2] = {strlen(username), buflen};

	res = PQexecParams(conf->conn, conf->aclquery, 2, NULL, values, lengths, NULL, 0);

	if (PQresultStatus(res) != PGRES_TUPLES_OK) {
		fprintf(stderr, "%s\n", PQresultErrorMessage(res));
		match = BACKEND_ERROR;

		//try to reset connection if failing because of database connection lost
		if(PQstatus(conf->conn) == CONNECTION_BAD){
			_log(LOG_NOTICE, "Noticed a postgres connection loss. Trying to reconnect ...\n");
			//try to reinitiate the database connection
			PQreset(conf->conn);
		}

		goto out;
	}
	if (PQnfields(res) != 1) {
		fprintf(stderr, "numfields not ok\n");
		goto out;
	}
	int rec_count = PQntuples(res);
	int row = 0;
	for (row = 0; row < rec_count; row++) {
		if ((v = PQgetvalue(res, row, 0)) != NULL) {

			/*
			 * Check mosquitto_match_topic. If true, if true, set
			 * match and break out of loop.
			 */

			char *expanded;

			t_expand(clientid, username, v, &expanded);
			if (expanded && *expanded) {
				mosquitto_topic_matches_sub(expanded, topic, &bf);
				if (bf) match = BACKEND_ALLOW;
				_log(LOG_DEBUG, "  postgres: topic_matches(%s, %s) == %d",
				     expanded, v, bf);

				free(expanded);
			}
		}
		if (match != BACKEND_DEFER) {
			break;
		}
	}

out:

	PQclear(res);

	return (match);
}
Exemple #16
0
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);
}
Exemple #17
0
int topic_matches_sub(const char *sub, const char *topic, bool *result)
{
	return mosquitto_topic_matches_sub(sub, topic, result);
}
int be_mysql_aclcheck(void *handle, const char *username, const char *topic, int acc)
{
	struct mysql_backend *conf = (struct mysql_backend *)handle;
	char *query = NULL, *u = NULL, *v;
	long ulen;
	int match = 0;
	bool bf;
	MYSQL_RES *res = NULL;
	MYSQL_ROW rowdata;

	if (!conf || !conf->aclquery)
		return (FALSE);

	if (mysql_ping(conf->mysql)) {
		fprintf(stderr, "%s\n", mysql_error(conf->mysql));
		if (!auto_connect(conf)) {
			return (FALSE);
		}
	}

	if ((u = escape(conf, username, &ulen)) == NULL)
		return (FALSE);

	if ((query = malloc(strlen(conf->aclquery) + ulen + 128)) == NULL) {
		free(u);
		return (FALSE);
	}
	sprintf(query, conf->aclquery, u, acc);
	free(u);

	//_log(LOG_DEBUG, "SQL: %s", query);

	if (mysql_query(conf->mysql, query)) {
		_log(LOG_NOTICE, "%s", mysql_error(conf->mysql));
		goto out;
	}

	res = mysql_store_result(conf->mysql);
	if (mysql_num_fields(res) != 1) {
		fprintf(stderr, "numfields not ok\n");
		goto out;
	}

	while (match == 0 && (rowdata = mysql_fetch_row(res)) != NULL) {
		if ((v = rowdata[0]) != NULL) {

			/* Check mosquitto_match_topic. If true,
			 * if true, set match and break out of loop. */

			// FIXME: does this need special work for %c and %u ???
			mosquitto_topic_matches_sub(v, topic, &bf);
			match |= bf;
			_log(LOG_DEBUG, "  mysql: topic_matches(%s, %s) == %d",
				topic, v, bf);
		}
	}

   out:

	mysql_free_result(res);
	free(query);

	return (match);
}