Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Commit

Permalink
- fixed build issue
Browse files Browse the repository at this point in the history
Signed-off-by: Hayden Briese <[email protected]>
  • Loading branch information
hbriese committed Jul 18, 2020
1 parent 80d6ef2 commit a4f5473
Show file tree
Hide file tree
Showing 2 changed files with 301 additions and 0 deletions.
219 changes: 219 additions & 0 deletions src/Service.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
#include "Service.hpp"

fc::Service::Service(const path &config_path, bool daemon)
: controller(config_path) {
if (daemon)
daemonize();
}

fc::Service::~Service() {
disable_controller();
if (server)
server->Shutdown();
}

void fc::Service::run() {
try {
if (service_running()) {
LOG(llvl::fatal) << "Only 1 instance may be run";
return;
}

// TODO: use SSL
// auto ssl_options = grpc::SslServerCredentialsOptions();
// ...
// auto creds = grpc::SslServerCredentials(ssl_options);

auto creds = grpc::InsecureServerCredentials();
ServerBuilder builder;
server = builder.AddListeningPort(SERVICE_ADDR, creds)
.RegisterService(this)
.BuildAndStart();

if (server) {
enable_controller();
server->Wait();
}
} catch (std::exception &e) {
LOG(llvl::fatal) << e.what();
throw e;
}
}

void fc::Service::enable_controller() {
if (controller.disabled())
controller_thread = thread([this] { controller.enable(); });
}

void fc::Service::disable_controller() {
controller.disable();
controller_thread.interrupt();
}

Status fc::Service::StopService([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
[[maybe_unused]] fc_pb::Empty *resp) {
disable_controller();
thread([&] { server->Shutdown(); }).detach();
return Status::OK;
}

Status fc::Service::Enable([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
[[maybe_unused]] fc_pb::Empty *resp) {
enable_controller();
return Status::OK;
}

Status fc::Service::Disable([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
[[maybe_unused]] fc_pb::Empty *resp) {
disable_controller();
return Status::OK;
}

Status fc::Service::Reload([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
[[maybe_unused]] fc_pb::Empty *resp) {
controller.reload();
return Status::OK;
}

Status fc::Service::NvInit([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
[[maybe_unused]] fc_pb::Empty *resp) {
controller.nv_init();
return Status::OK;
}

Status fc::Service::ControllerStatus([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
fc_pb::ControllerState *resp) {
auto s = static_cast<fc_pb::ControllerState_State>(controller.state);
resp->set_state(s);
return Status::OK;
}

Status fc::Service::GetDevices([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
fc_pb::Devices *devices) {
controller.devices.to(*devices);
return Status::OK;
}

Status fc::Service::SetDevices([[maybe_unused]] ServerContext *context,
const fc_pb::Devices *devices,
[[maybe_unused]] fc_pb::Empty *e) {
controller.devices = fc::Devices();
controller.devices.from(*devices);
return Status::OK;
}

Status
fc::Service::GetEnumeratedDevices([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *req,
fc_pb::Devices *devices) {
Devices(true).to(*devices);
return Status::OK;
}

Status fc::Service::Test([[maybe_unused]] ServerContext *context,
const fc_pb::TestRequest *e,
ServerWriter<fc_pb::TestResponse> *writer) {
auto fit = controller.devices.fans.find(e->device_label());
if (fit == controller.devices.fans.end())
// TODO: error << device isn't found
return Status::OK;

auto cb = [&](int &status) {
fc_pb::TestResponse resp;
resp.set_status(status);
if (status == 100)
writer->WriteLast(resp, grpc::WriteOptions());
else
writer->Write(resp);
};

controller.test(*fit->second, e->forced(), cb);

return Status::OK;
}

Status fc::Service::GetControllerConfig([[maybe_unused]] ServerContext *context,
[[maybe_unused]] const fc_pb::Empty *e,
fc_pb::ControllerConfig *config) {
controller.to(*config);
return Status::OK;
}

Status fc::Service::SetControllerConfig([[maybe_unused]] ServerContext *context,
const fc_pb::ControllerConfig *config,
[[maybe_unused]] fc_pb::Empty *e) {
controller.from(*config);
controller.reload();
return Status::OK;
}

void fc::Service::daemonize() {
const auto fork_thread = []() {
pid_t pid = fork();

// On success: child's PID is returned in parent, 0 returned in child
if (pid >= 0)
exit(EXIT_SUCCESS);
else if (pid == -1) { // On failure: -1 returned in parent
LOG(llvl::fatal) << "Failed to fork off parent";
exit(EXIT_FAILURE);
}
};

// Daemonize process by forking, creating new session, then forking again
fork_thread();

// Create a new session for the child
if (setsid() < 0) {
LOG(llvl::fatal) << "Failed to fork off parent";
exit(EXIT_FAILURE);
}

fork_thread();

// Redirect standard file descriptors to /dev/null
const char *dnull = "/dev/null";
stdin = fopen(dnull, "r");
stdout = fopen(dnull, "r+");
stderr = fopen(dnull, "r+");

// 664 (rw-rw-r--) files; 775 (rwxrwxr-x) directories
umask(002);

// Set working dir to /
if (chdir("/") < 0)
LOG(llvl::error) << "Failed to set working directory to '/'";
}

bool fc::Service::service_running() {
auto creds = grpc::InsecureChannelCredentials();
auto channel = grpc::CreateChannel(Util::SERVICE_ADDR, creds);
channel->WaitForConnected(Util::deadline(200));
return channel->GetState(true) == GRPC_CHANNEL_READY;
}

// void fc::Service::signal_handler(int signal) {
// switch (signal) {
// case SIGINT:
// case SIGQUIT:
// case SIGTERM:
// fc::Controller::disable();
// SERVER->Shutdown();
// break;
// default:
// LOG(llvl::warning) << "Unhandled signal (" << signal
// << "): " << strsignal(signal);
// }
//}
//
// void fc::Service::register_signal_handler() {
// for (const auto &s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1})
// std::signal(s, &fc::Service::signal_handler);
//}
82 changes: 82 additions & 0 deletions src/Service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef FANCON_SERVICE_HPP
#define FANCON_SERVICE_HPP

#include "Controller.hpp"
#include <csignal>
#include <grpcpp/grpcpp.h>
#include <grpcpp/server.h>
#include <grpcpp/support/status.h>
#include <mutex>
#include <sys/stat.h>

#include "proto/DevicesSpec.grpc.pb.h"
#include "proto/DevicesSpec.pb.h"

using fc::Controller;
using fc::Util::SERVICE_ADDR;
using fc_pb::Empty;
using grpc::ChannelCredentials;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerReaderWriter;
using grpc::ServerWriter;
using grpc::Status;
using std::lock_guard;
using std::mutex;

namespace fc {
class Service : public fc_pb::DService::Service {
public:
explicit Service(const path &config_path, bool daemon = false);
~Service() override;

void run();

Status StopService(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Empty *resp) override;
Status Enable(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Empty *resp) override;
Status Disable(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Empty *resp) override;
Status Reload(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Empty *resp) override;
Status NvInit(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Empty *resp) override;
Status ControllerStatus(ServerContext *context, const fc_pb::Empty *e,
fc_pb::ControllerState *resp) override;

Status GetDevices(ServerContext *context, const fc_pb::Empty *e,
fc_pb::Devices *devices) override;
Status SetDevices(ServerContext *context, const fc_pb::Devices *devices,
fc_pb::Empty *e) override;
Status GetEnumeratedDevices(ServerContext *context, const fc_pb::Empty *req,
fc_pb::Devices *devices) override;
Status Test(ServerContext *context, const fc_pb::TestRequest *e,
ServerWriter<fc_pb::TestResponse> *writer) override;

Status GetControllerConfig(ServerContext *context, const fc_pb::Empty *e,
fc_pb::ControllerConfig *config) override;
Status SetControllerConfig(ServerContext *context,
const fc_pb::ControllerConfig *config,
fc_pb::Empty *e) override;

private:
fc::Controller controller;
unique_ptr<Server> server;
thread controller_thread;
mutex test_writer_mutex;

void enable_controller();
void disable_controller();
static void daemonize();

static bool service_running();

// static void signal_handler(int signal);
// static void register_signal_handler();
};
} // namespace fc

#endif // FANCON_SERVICE_HPP

0 comments on commit a4f5473

Please sign in to comment.