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