Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
{
	int i;
	struct mosquitto *new_context = NULL;
	int null_index = -1;
	struct mosquitto **tmp_contexts;
	char hostname[256];
	int len;
	char *id;

	assert(db);
	assert(bridge);

	if(bridge->clientid){
		id = _mosquitto_strdup(bridge->clientid);
	}else{
		if(!gethostname(hostname, 256)){
			len = strlen(hostname) + strlen(bridge->name) + 2;
			id = _mosquitto_malloc(len);
			if(!id){
				return MOSQ_ERR_NOMEM;
			}
			snprintf(id, len, "%s.%s", hostname, bridge->name);
		}else{
			return 1;
		}
	}
	if(!id){
		return MOSQ_ERR_NOMEM;
	}

	/* Search for existing id (possible from persistent db) and also look for a
	 * gap in the db->contexts[] array in case the id isn't found. */
	for(i=0; i<db->context_count; i++){
		if(db->contexts[i]){
			if(!strcmp(db->contexts[i]->id, id)){
				new_context = db->contexts[i];
				break;
			}
		}else if(db->contexts[i] == NULL && null_index == -1){
			null_index = i;
			break;
		}
	}
	if(!new_context){
		/* id wasn't found, so generate a new context */
		new_context = mqtt3_context_init(-1);
		if(!new_context){
			return MOSQ_ERR_NOMEM;
		}
		if(null_index == -1){
			/* There were no gaps in the db->contexts[] array, so need to append. */
			db->context_count++;
			tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*db->context_count);
			if(tmp_contexts){
				db->contexts = tmp_contexts;
				db->contexts[db->context_count-1] = new_context;
			}else{
				_mosquitto_free(new_context);
				return MOSQ_ERR_NOMEM;
			}
		}else{
			db->contexts[null_index] = new_context;
		}
		new_context->id = id;
	}else{
		/* id was found, so context->id already in memory. */
		_mosquitto_free(id);
	}
	new_context->bridge = bridge;
	new_context->is_bridge = true;

	new_context->username = new_context->bridge->username;
	new_context->password = new_context->bridge->password;

#ifdef WITH_TLS
	new_context->tls_cafile = new_context->bridge->tls_cafile;
	new_context->tls_capath = new_context->bridge->tls_capath;
	new_context->tls_certfile = new_context->bridge->tls_certfile;
	new_context->tls_keyfile = new_context->bridge->tls_keyfile;
	new_context->tls_cert_reqs = SSL_VERIFY_PEER;
	new_context->tls_version = new_context->bridge->tls_version;
	new_context->tls_insecure = new_context->bridge->tls_insecure;
#ifdef REAL_WITH_TLS_PSK
	new_context->tls_psk_identity = new_context->bridge->tls_psk_identity;
	new_context->tls_psk = new_context->bridge->tls_psk;
#endif
#endif

	bridge->try_private_accepted = true;

	return mqtt3_bridge_connect(db, new_context);
}
Exemplo n.º 5
0
int mqtt3_socket_accept(struct _mosquitto_db *db, int listensock)
{
	int i;
	int j;
	int new_sock = -1;
	struct mosquitto **tmp_contexts = NULL;
	struct mosquitto *new_context;
	int opt = 1;
#ifdef WITH_TLS
	BIO *bio;
	int rc;
#endif
#ifdef WITH_WRAP
	struct request_info wrap_req;
#endif

	new_sock = accept(listensock, NULL, 0);
	if(new_sock == INVALID_SOCKET) return -1;

#ifndef WIN32
	/* Set non-blocking */
	opt = fcntl(new_sock, F_GETFL, 0);
	if(opt == -1 || fcntl(new_sock, F_SETFL, opt | O_NONBLOCK) == -1){
		/* If either fcntl fails, don't want to allow this client to connect. */
		close(new_sock);
		return -1;
	}
#else
	if(ioctlsocket(new_sock, FIONBIO, &opt)){
		closesocket(new_sock);
		return INVALID_SOCKET;
	}
#endif

#ifdef WITH_WRAP
	/* Use tcpd / libwrap to determine whether a connection is allowed. */
	request_init(&wrap_req, RQ_FILE, new_sock, RQ_DAEMON, "mosquitto", 0);
	fromhost(&wrap_req);
	if(!hosts_access(&wrap_req)){
		/* Access is denied */
		_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection denied access by tcpd.");
		COMPAT_CLOSE(new_sock);
		return -1;
	}else{
#endif
		new_context = mqtt3_context_init(new_sock);
		if(!new_context){
			COMPAT_CLOSE(new_sock);
			return -1;
		}
		for(i=0; i<db->config->listener_count; i++){
			for(j=0; j<db->config->listeners[i].sock_count; j++){
				if(db->config->listeners[i].socks[j] == listensock){
					new_context->listener = &db->config->listeners[i];
					break;
				}
			}
		}
		if(!new_context->listener){
			COMPAT_CLOSE(new_sock);
			return -1;
		}

		if(new_context->listener->max_connections > 0 && new_context->listener->client_count >= new_context->listener->max_connections){
			COMPAT_CLOSE(new_sock);
			return -1;
		}
		_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New connection from %s.", new_context->address);
		for(i=0; i<db->context_count; i++){
			if(db->contexts[i] == NULL){
				db->contexts[i] = new_context;
				break;
			}
		}
		if(i==db->context_count){
			tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*(db->context_count+1));
			if(tmp_contexts){
				db->context_count++;
				db->contexts = tmp_contexts;
				db->contexts[db->context_count-1] = new_context;
			}else{
				mqtt3_context_cleanup(NULL, new_context, true);
			}
		}
		new_context->listener->client_count++;

#ifdef WITH_TLS
		/* TLS init */
		for(i=0; i<db->config->listener_count; i++){
			for(j=0; j<db->config->listeners[i].sock_count; j++){
				if(db->config->listeners[i].socks[j] == listensock){
					if(db->config->listeners[i].ssl_ctx){
						new_context->ssl = SSL_new(db->config->listeners[i].ssl_ctx);
						if(!new_context->ssl){
							COMPAT_CLOSE(new_sock);
							return -1;
						}
						SSL_set_ex_data(new_context->ssl, tls_ex_index_context, new_context);
						SSL_set_ex_data(new_context->ssl, tls_ex_index_listener, &db->config->listeners[i]);
						new_context->want_read = true;
						new_context->want_write = true;
						bio = BIO_new_socket(new_sock, BIO_NOCLOSE);
						SSL_set_bio(new_context->ssl, bio, bio);
						rc = SSL_accept(new_context->ssl);
						if(rc != 1){
							rc = SSL_get_error(new_context->ssl, rc);
							if(rc == SSL_ERROR_WANT_READ){
								new_context->want_read = true;
							}else if(rc == SSL_ERROR_WANT_WRITE){
								new_context->want_write = true;
							}
						}
					}
				}
			}
		}
#endif

#ifdef WITH_WRAP
	}
#endif
	return new_sock;
}
Exemplo n.º 6
0
int mqtt3_socket_accept(struct mosquitto_db *db, int listensock)
{
	int i;
	int j;
	int new_sock = -1;
	struct mosquitto **tmp_contexts = NULL;
	struct mosquitto *new_context;
	int opt = 1;

	new_sock = accept(listensock, NULL, 0);
	if(new_sock == INVALID_SOCKET) return -1;

#ifdef WITH_SYS_TREE
	g_socket_connections++;
#endif

	/* Set non-blocking */
	opt = fcntl(new_sock, F_GETFL, 0);
	if(opt == -1 || fcntl(new_sock, F_SETFL, opt | O_NONBLOCK) == -1){
		/* If either fcntl fails, don't want to allow this client to connect. */
		close(new_sock);
		return -1;
	}

	//初始化个跟客户端连接的context,里面会设置客户端的IP地址,这里可以考虑不在里面做,accept的时候参数中完成即可
	new_context = mqtt3_context_init(new_sock);
	if(!new_context){
		COMPAT_CLOSE(new_sock);
		return -1;
	}
	for(i=0; i<db->config->listener_count; i++){//循环找每一个listeners,找到我是属于哪个listeners.实际上epoll后就不需要这些东西了
		for(j=0; j<db->config->listeners[i].sock_count; j++){
			if(db->config->listeners[i].socks[j] == listensock){
				new_context->listener = &db->config->listeners[i];//指向我所属的listener
				break;
			}
		}
	}
	if(!new_context->listener){
		COMPAT_CLOSE(new_sock);
		return -1;
	}

	if(new_context->listener->max_connections > 0 && new_context->listener->client_count >= new_context->listener->max_connections){
		_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied: max_connections exceeded.", new_context->address);
		COMPAT_CLOSE(new_sock);
		return -1;
	}
	_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New connection from %s on port %d.", new_context->address, new_context->listener->port);
	for(i=0; i<db->context_count; i++){//找一个空的contexts结构,指向这一个空连接
		if(db->contexts[i] == NULL){
			db->contexts[i] = new_context;
			break;
		}
	}
	if(i==db->context_count){//没有了,重新realloc一个,这个代价很大的。所以建议申请2倍,保留一些空余的,到一定程度的时候每次增加32个也行
		tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*(db->context_count+1));
		if(tmp_contexts){
			db->context_count += 1;//暂时改为一次增长32个,不然每次都realloc很恐怖 
			db->contexts = tmp_contexts;//这样的话,所有人都不能用指向contexts数组某个位置的指针来标识这个连接,比如放到epoll里面去世不行的
			db->contexts[i] = new_context;
		}else{
			//到这里,说明contexts[]数组不够了,而且relloac也失败,怎么办,只能丢掉这个连接了。但是下面并没有return -1,而且还去访问了。是个bug
			// Out of memory
			mqtt3_context_cleanup(NULL, new_context, true);
			return -1 ;//必须return,否则下面会core
		}
	}
	// If we got here then the context's DB index is "i" regardless of how we got here
	new_context->db_index = i;
	new_context->listener->client_count++;


	return new_sock;
}