blob: 704b400288683a56b788ca78b6b8a1342424b28e [file] [log] [blame] [edit]
#include "grpc_instance.h"
#include <chrono> // NOLINT(build/c++11)
#include <memory>
#include <sstream>
#include <string>
#include <thread> // NOLINT(build/c++11)
#include "absl/log/log.h"
#include "grpcblob_defs.h"
#include "smbios_file.h"
#include "grpcpp/security/server_credentials.h"
namespace blobs {
// Arbitrary constant to avoid overlap with other services
constexpr int basePort = 10166;
[[nodiscard]] std::string GrpcInstance::threadId(
const std::thread& thread) const {
std::stringstream ss;
ss << thread.get_id();
return ss.str();
}
[[nodiscard]] bool GrpcInstance::validatePreviousFile() const {
LOG(INFO) << "GrpcInstance::validatePreviousFile: " << instance;
// Instance number must be set in order to build correct filename
SmbiosEntry entry(instance, basePath_);
std::string fileName = entry.getFilename();
if (!(entry.loadFromFile(fileName))) {
// This is normal if running for first time on clean filesystem
LOG(ERROR) << "Could not restore SMBIOS from file: " << fileName;
return false;
}
std::string errorMessage = entry.validate();
if (!(errorMessage.empty())) {
LOG(ERROR) << "Loaded SMBIOS content failed validation: " << errorMessage;
return false;
}
return true;
}
void GrpcInstance::restoreLink() {
// Obtain consistent filename creation by asking entry for filename
SmbiosEntry entry(instance, basePath_);
if (!(validatePreviousFile())) {
// Not error, normal if running for the first time on a fresh system
LOG(INFO) << "Unable to restore from previous file: " << instance;
return;
}
// The content is restored, update app as if file came from gRPC
bool accepted = smbiosServiceCallback->acceptEntry(entry, false);
if (!accepted) {
LOG(ERROR) << "Unable to restore to previous link: " << instance;
return;
}
LOG(INFO) << "Restoring previous request content: " << instance;
}
void GrpcInstance::start() {
// Bias, because port number range 1-based but instances are 0-based
int offset = instance + 1;
if (offset == numInstances) {
// Base port unused, but still open, highest instance for testing
offset = 0;
}
// The instances are at consecutive port numbers
int port = basePort + offset;
std::string address = "[::]:";
address += std::to_string(port);
grpcCredentials = grpc::InsecureServerCredentials();
grpcBuilder.AddListeningPort(address, grpcCredentials);
grpcBuilder.RegisterService(smbiosServiceCallback.get());
grpcBuilder.RegisterService(biosSettingGrpcService.get());
grpcBuilder.RegisterService(bmServiceCallback.get());
grpcBuilder.RegisterService(bootTimeServiceCallback.get());
LOG(INFO) << "Claimed gRPC address: " << address << " for " << instance;
grpcServer = grpcBuilder.BuildAndStart();
LOG(INFO) << "Started gRPC server: " << instance;
// Server is up, give it the thread that it needs to make progress
grpcThread = std::make_unique<std::thread>([this]() { this->threadRun(); });
LOG(INFO) << "Thread " << threadId(*grpcThread) << " created: " << instance;
}
void GrpcInstance::threadRun() {
restoreLink();
// This will block until Shutdown() is called
grpcServer->Wait();
LOG(INFO) << "Finishing gRPC thread: " << instance;
}
void GrpcInstance::stop() {
LOG(INFO) << "Stopping gRPC thread: " << instance;
// Tells gRPC to allow Wait() to return
grpcServer->Shutdown(std::chrono::system_clock::now());
LOG(INFO) << "Cleaning up gRPC thread: " << instance;
// This will block until threadRun() returns
grpcThread->join();
LOG(INFO) << "Stopped gRPC server: " << instance;
}
} // namespace blobs