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_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; char address[1024]; #endif new_sock = accept(listensock, NULL, 0); if(new_sock == INVALID_SOCKET) return -1; g_socket_connections++; #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 */ if(!_mosquitto_socket_get_address(new_sock, address, 1024)){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied access by tcpd.", address); } 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){ _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.", 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; }