blob: f9a0857cecb02f73e852e015222d1afc48cccb16 [file] [log] [blame]
/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SmbConnectionControllerService.h"
#include "core/Resource.h"
#include "utils/OsUtils.h"
#include "utils/expected.h"
namespace org::apache::nifi::minifi::extensions::smb {
void SmbConnectionControllerService::initialize() {
setSupportedProperties(Properties);
}
void SmbConnectionControllerService::onEnable() {
std::string hostname;
std::string share;
if (!getProperty(Hostname, hostname))
throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Missing hostname");
if (!getProperty(Share, share))
throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Missing share");
server_path_ = "\\\\" + hostname + "\\" + share;
auto password = getProperty(Password);
auto username = getProperty(Username);
if (password.has_value() != username.has_value())
throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Either both a username and a password, or neither of them should be provided.");
if (username.has_value())
credentials_.emplace(Credentials{.username = *username, .password = *password});
else
credentials_.reset();
net_resource_ = {
.dwType = RESOURCETYPE_DISK,
.lpLocalName = nullptr,
.lpRemoteName = server_path_.data(),
.lpProvider = nullptr,
};
}
void SmbConnectionControllerService::notifyStop() {
auto disconnection_result = disconnect();
if (!disconnection_result)
logger_->log_error("Error while disconnecting from SMB: %s", disconnection_result.error().message());
}
gsl::not_null<std::shared_ptr<SmbConnectionControllerService>> SmbConnectionControllerService::getFromProperty(const core::ProcessContext& context, const core::PropertyReference& property) {
std::shared_ptr<SmbConnectionControllerService> smb_connection_controller_service;
if (auto connection_controller_name = context.getProperty(property)) {
smb_connection_controller_service = std::dynamic_pointer_cast<SmbConnectionControllerService>(context.getControllerService(*connection_controller_name));
}
if (!smb_connection_controller_service) {
throw minifi::Exception(ExceptionType::PROCESS_SCHEDULE_EXCEPTION, "Missing SMB Connection Controller Service");
}
return gsl::make_not_null(smb_connection_controller_service);
}
nonstd::expected<void, std::error_code> SmbConnectionControllerService::connect() {
auto connection_result = WNetAddConnection2A(&net_resource_,
credentials_ ? credentials_->password.c_str() : nullptr,
credentials_ ? credentials_->username.c_str() : nullptr,
CONNECT_TEMPORARY);
if (connection_result == NO_ERROR)
return {};
return nonstd::make_unexpected(utils::OsUtils::windowsErrorToErrorCode(connection_result));
}
nonstd::expected<void, std::error_code> SmbConnectionControllerService::disconnect() {
auto disconnection_result = WNetCancelConnection2A(server_path_.c_str(), 0, true);
if (disconnection_result == NO_ERROR)
return {};
return nonstd::make_unexpected(utils::OsUtils::windowsErrorToErrorCode(disconnection_result));
}
bool SmbConnectionControllerService::isConnected() {
std::error_code error_code;
auto exists = std::filesystem::exists(server_path_, error_code);
if (error_code) {
logger_->log_debug("std::filesystem::exists(%s) failed due to %s", server_path_, error_code.message());
return false;
}
return exists;
}
std::error_code SmbConnectionControllerService::validateConnection() {
if (isConnected()) {
return std::error_code();
}
auto connection_result = connect();
if (!connection_result) {
return connection_result.error();
}
return std::error_code();
}
REGISTER_RESOURCE(SmbConnectionControllerService, ControllerService);
} // namespace org::apache::nifi::minifi::extensions::smb