Browse Source

control: server side support for querying load paths.

Support for querying the service loader mechanism (currently there is
only one) and its details (the paths from which it loads service
descriptions).
Davin McCall 5 năm trước cách đây
mục cha
commit
fcc01d7979
4 tập tin đã thay đổi với 82 bổ sung0 xóa
  1. 44 0
      src/control.cc
  2. 6 0
      src/includes/control-cmds.h
  3. 6 0
      src/includes/control.h
  4. 26 0
      src/includes/service.h

+ 44 - 0
src/control.cc

@@ -88,6 +88,9 @@ bool control_conn_t::process_packet()
     if (pktType == DINIT_CP_REM_DEP) {
         return rm_service_dep();
     }
+    if (pktType == DINIT_CP_QUERY_LOAD_MECH) {
+        return query_load_mech();
+    }
 
     // Unrecognized: give error response
     char outbuf[] = { DINIT_RP_BADREQ };
@@ -548,6 +551,47 @@ bool control_conn_t::rm_service_dep()
     return true;
 }
 
+bool control_conn_t::query_load_mech()
+{
+    if (services->get_set_type_id() == SSET_TYPE_DIRLOAD) {
+        dirload_service_set *dss = static_cast<dirload_service_set *>(services);
+        std::vector<char> reppkt;
+        reppkt.resize(2 + sizeof(uint32_t) * 2);  // packet type, loader type, packet size, # dirs
+        reppkt[0] = DINIT_RP_LOADER_MECH;
+        reppkt[1] = SSET_TYPE_DIRLOAD;
+
+        // Number of directories in load path:
+        uint32_t sdirs = dss->get_service_dir_count();
+        std::memcpy(reppkt.data() + 2 + sizeof(uint32_t), &sdirs, sizeof(sdirs));
+
+        for (int i = 0; i < sdirs; i++) {
+            const char *sdir = dss->get_service_dir(i);
+            uint32_t dlen = std::strlen(sdir);
+            auto cursize = reppkt.size();
+            reppkt.resize(cursize + sizeof(dlen) + dlen);
+            std::memcpy(reppkt.data() + cursize, &dlen, sizeof(dlen));
+            std::memcpy(reppkt.data() + cursize + sizeof(dlen), sdir, dlen);
+        }
+
+        // Total packet size:
+        uint32_t fsize = reppkt.size();
+        std::memcpy(reppkt.data() + 2, &fsize, sizeof(fsize));
+
+        if (! queue_packet(std::move(reppkt))) return false;
+        rbuf.consume(1);
+        chklen = 0;
+        return true;
+    }
+    else {
+        // If we don't know how to deal with the service set type, send a NAK reply:
+        char ack_rep[] = { DINIT_RP_NAK };
+        if (! queue_packet(ack_rep, 1)) return false;
+        rbuf.consume(1);
+        chklen = 0;
+        return true;
+    }
+}
+
 control_conn_t::handle_t control_conn_t::allocate_service_handle(service_record *record)
 {
     // Try to find a unique handle (integer) in a single pass. Since the map is ordered, we can search until

+ 6 - 0
src/includes/control-cmds.h

@@ -33,6 +33,9 @@ constexpr static int DINIT_CP_SHUTDOWN = 10;
 constexpr static int DINIT_CP_ADD_DEP = 11;
 constexpr static int DINIT_CP_REM_DEP = 12;
 
+// Query service load path / mechanism:
+constexpr static int DINIT_CP_QUERY_LOAD_MECH = 13;
+
 // Replies:
 
 // Reply: ACK/NAK to request
@@ -69,6 +72,9 @@ constexpr static int DINIT_RP_ALREADYSS = 61;
 constexpr static int DINIT_RP_SVCINFO = 62;
 constexpr static int DINIT_RP_LISTDONE = 63;
 
+// Service loader information:
+constexpr static int DINIT_RP_LOADER_MECH = 64;
+
 // Information:
 
 // Service event occurred (4-byte service handle, 1 byte event code)

+ 6 - 0
src/includes/control.h

@@ -145,12 +145,18 @@ class control_conn_t : private service_listener
     // Process an UNLOADSERVICE packet.
     bool process_unload_service();
 
+    // List all loaded services and their state.
     bool list_services();
 
+    // Add a dependency between two services.
     bool add_service_dep();
 
+    // Remove a dependency between two services.
     bool rm_service_dep();
 
+    // Query service path / load mechanism.
+    bool query_load_mech();
+
     // Notify that data is ready to be read from the socket. Returns true if the connection should
     // be closed.
     bool data_ready() noexcept;

+ 26 - 0
src/includes/service.h

@@ -731,6 +731,10 @@ inline auto extract_console_queue(service_record *sr) -> decltype(sr->console_qu
     return sr->console_queue_node;
 }
 
+// Service set type identifiers:
+constexpr int SSET_TYPE_NONE = 0;
+constexpr int SSET_TYPE_DIRLOAD = 1;
+
 /*
  * A service_set, as the name suggests, manages a set of services.
  *
@@ -958,6 +962,13 @@ class service_set
     {
         return shutdown_type;
     }
+
+    // Get an identifier for the run-time type of the service set (similar to typeid, but without
+    // requiring RTTI to be enabled during compilation).
+    virtual int get_set_type_id()
+    {
+        return SSET_TYPE_NONE;
+    }
 };
 
 // A service directory entry, tracking the directory as a nul-terminated string, which may either
@@ -1013,7 +1024,22 @@ class dirload_service_set : public service_set
         service_dirs.emplace_back(service_dir_p, dyn_allocd);
     }
 
+    int get_service_dir_count()
+    {
+        return service_dirs.size();
+    }
+
+    const char * get_service_dir(int n)
+    {
+        return service_dirs[n].get_dir();
+    }
+
     service_record *load_service(const char *name) override;
+
+    int get_set_type_id() override
+    {
+        return SSET_TYPE_DIRLOAD;
+    }
 };
 
 #endif