Commit 3c6db066 authored by jan.koester's avatar jan.koester
Browse files

test

parent 39fd092f
Loading
Loading
Loading
Loading
+1 −0
Changes for CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ configure_file(config.h.in ${CMAKE_BINARY_DIR}/config.h)
add_library(sysbus STATIC
    src/sysbus/message.cpp
    src/sysbus/client.cpp
    src/sysbus/service.cpp
)
target_include_directories(sysbus PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+18 −0
Changes for include/sysbus/client.h: 18 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,12 @@ constexpr const char *Subscribe = "Subscribe";
constexpr const char *Reboot = "Reboot";
constexpr const char *PowerOff = "PowerOff";

// Services: other daemons register a name (root only, see sysbus/service.h);
// a call with the field "sysbus.destination" set to that name is forwarded
// to the daemon and its reply passed back (Client::callService()).
constexpr const char *RegisterService = "RegisterService";  // name
constexpr const char *ListServices = "ListServices";        // -> service, service_pid (repeated)

// Network interfaces. Configurations are .network files in
// /etc/syslite/network; Create/Edit/Delete change only the files, Start,
// Reload and Restart apply them.
@@ -66,6 +72,9 @@ constexpr const char *UnknownInterface = "sysbus.Error.UnknownInterface";
constexpr const char *AccessDenied = "sysbus.Error.AccessDenied";
constexpr const char *Failed = "sysbus.Error.Failed";
constexpr const char *InvalidArgs = "sysbus.Error.InvalidArgs";
constexpr const char *ServiceUnknown = "sysbus.Error.ServiceUnknown";  // no such service registered
constexpr const char *ServiceGone = "sysbus.Error.ServiceGone";        // it went away before replying
constexpr const char *Timeout = "sysbus.Error.Timeout";                // it didn't reply in time
} // namespace error

struct UnitInfo {
@@ -136,6 +145,15 @@ public:
                 const std::vector<std::pair<std::string, std::string>> &args = {},
                 int timeoutMs = 90000);

    // A method of a registered service (forwarded by the bus, see
    // sysbus/service.h). Errors as for call(); an unknown service is
    // sysbus.Error.ServiceUnknown.
    Message callService(const std::string &service, const std::string &member,
                        const std::vector<std::pair<std::string, std::string>> &args = {},
                        int timeoutMs = 90000);
    // The registered services' names.
    std::vector<std::string> listServices();

    // Unit control: true on success, otherwise see lastError().
    bool startUnit(const std::string &name);
    bool stopUnit(const std::string &name);
+65 −0
Changes for include/sysbus/service.h: 65 added lines, 0 removed lines.
Original line number Diff line number Diff line
#pragma once

// A daemon that offers methods on sysbus under a name of its own:
//
//   sysbus::Service svc;
//   svc.start("sharedd", [](const sysbus::Message &call, const sysbus::Caller &who) {
//       if (call.member == "ListShares") ...
//       return sysbus::Message::reply(call);
//   });
//   // in the main loop: poll(svc.fd(), POLLIN) and then svc.process()
//
// Registering needs root (the bus only takes names from uid 0); callers
// reach it with Client::callService("sharedd", ...). Each call carries the
// caller's uid and pid as the bus saw them (SO_PEERCRED), so a service can
// refuse changes from non-root callers. When the bus goes away (syslite
// restarts), process() returns false and start() can be called again.

#include "sysbus/message.h"

#include <functional>
#include <string>
#include <sys/types.h>

namespace sysbus {

struct Caller {
    uid_t uid = static_cast<uid_t>(-1);
    pid_t pid = -1;
};

class Service {
public:
    // Returns the reply: Message::reply(call) or Message::error(call, ...).
    using Handler = std::function<Message(const Message &call, const Caller &caller)>;

    Service() = default;
    ~Service();
    Service(const Service &) = delete;
    Service &operator=(const Service &) = delete;

    bool start(const std::string &name, Handler handler, const std::string &path = SYSBUS_SOCKET);
    void stop();
    bool running() const { return _fd >= 0; }
    int fd() const { return _fd; }

    // Reads what arrived and answers the calls in it. false once the bus
    // connection is gone.
    bool process();

    // A signal to every subscribed client (the bus adds "sysbus.sender").
    bool emit(const std::string &signal, const std::vector<std::pair<std::string, std::string>> &fields = {});

    const std::string &name() const { return _name; }
    const std::string &lastError() const { return _lastError; }

private:
    int _fd = -1;
    uint32_t _serial = 0;
    std::string _name;
    Handler _handler;
    Decoder _decoder;
    std::string _lastError;
};

} // namespace sysbus
+18 −0
Changes for src/busserver.h: 18 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -47,12 +47,30 @@ private:
    void accept();
    void serve(int fd);
    void drop(int fd);
    // false if fd was dropped
    bool send(int fd, const sysbus::Message &msg);
    sysbus::Message busMethod(const sysbus::Message &call, int fd, BusPeer &peer, bool &handled);
    void route(const sysbus::Message &call, int fd, const BusPeer &peer, const std::string &dest);
    void answer(const sysbus::Message &reply, int fd);
    void expirePending();

    // a call forwarded to a service, waiting for its reply
    struct Pending {
        int callerFd;
        uint32_t callerSerial;
        int serviceFd;
        long sentMs;
    };
    static constexpr long ServiceTimeoutMs = 120000;

    int _listenFd = -1;
    std::string _path;
    Handler _handler;
    std::map<int, Client> _clients;
    uint32_t _signalSerial = 0;
    std::map<std::string, int> _services;   // name -> fd
    std::map<uint32_t, Pending> _pending;   // bus serial -> caller
    uint32_t _forwardSerial = 0;
};

} // namespace syslite
+15 −0
Changes for src/sysbus/client.cpp: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -161,6 +161,21 @@ Message Client::call(const std::string &member,
    }
}

Message Client::callService(const std::string &service, const std::string &member,
                            const std::vector<std::pair<std::string, std::string>> &args, int timeoutMs) {
    std::vector<std::pair<std::string, std::string>> all;
    all.reserve(args.size() + 1);
    all.emplace_back("sysbus.destination", service);
    all.insert(all.end(), args.begin(), args.end());
    return call(member, all, timeoutMs);
}

std::vector<std::string> Client::listServices() {
    Message r;
    if (!checkedCall(method::ListServices, {}, &r)) return {};
    return r.getAll("service");
}

bool Client::simpleCall(const char *member, const std::string &unit) {
    Message r = call(member, {{"unit", unitName(unit)}});
    if (r.type == MessageType::Error) {
Loading