Control protocol: implement QUERYSERVICENAME to get name from handle
authorDavin McCall <davmac@davmac.org>
Sun, 21 Jul 2019 05:08:50 +0000 (15:08 +1000)
committerDavin McCall <davmac@davmac.org>
Sun, 21 Jul 2019 05:08:50 +0000 (15:08 +1000)
src/control.cc
src/includes/control-cmds.h
src/includes/control.h

index 2f02a24359f3d035d6655053ab4e45081c14b28c..32573d2f316f68e288f01d324f94d437ff6aa1e8 100644 (file)
@@ -95,6 +95,9 @@ bool control_conn_t::process_packet()
     if (pktType == DINIT_CP_ENABLESERVICE) {
         return add_service_dep(true);
     }
+    if (pktType == DINIT_CP_QUERYSERVICENAME) {
+        return process_query_name();
+    }
 
     // Unrecognized: give error response
     char outbuf[] = { DINIT_RP_BADREQ };
@@ -623,6 +626,46 @@ bool control_conn_t::rm_service_dep()
     return true;
 }
 
+bool control_conn_t::process_query_name()
+{
+    // 1 byte packet type
+    // 1 byte reserved
+    // handle: service
+    constexpr int pkt_size = 2 + sizeof(handle_t);
+
+    if (rbuf.get_length() < pkt_size) {
+        chklen = pkt_size;
+        return true;
+    }
+
+    // Reply:
+    // 1 byte packet type = DINIT_RP_SERVICENAME
+    // 1 byte reserved
+    // uint16_t length
+    // N bytes name
+
+    handle_t handle;
+    rbuf.extract(&handle, 2, sizeof(handle));
+    rbuf.consume(pkt_size);
+    chklen = 0;
+
+    service_record *service = find_service_for_key(handle);
+    if (service == nullptr || service->get_name().length() > std::numeric_limits<uint16_t>::max()) {
+        char ack_rep[] = { DINIT_RP_ACK };
+        if (! queue_packet(ack_rep, 1)) return false;
+    }
+
+    std::vector<char> reply;
+    const std::string &name = service->get_name();
+    uint16_t name_length = name.length();
+    reply.resize(2 + sizeof(uint16_t) + name_length);
+    reply[0] = DINIT_RP_SERVICENAME;
+    memcpy(reply.data() + 2, &name_length, sizeof(name_length));
+    memcpy(reply.data() + 2 + sizeof(uint16_t), name.c_str(), name_length);
+
+    return queue_packet(std::move(reply));
+}
+
 bool control_conn_t::query_load_mech()
 {
     rbuf.consume(1);
@@ -664,8 +707,7 @@ bool control_conn_t::query_load_mech()
             if (try_path_size == 0) {
                 // overflow.
                 char ack_rep[] = { DINIT_RP_NAK };
-                if (! queue_packet(ack_rep, 1)) return false;
-                return true;
+                return queue_packet(ack_rep, 1);
             }
         }
 
@@ -693,8 +735,7 @@ bool control_conn_t::query_load_mech()
     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;
-        return true;
+        return queue_packet(ack_rep, 1);
     }
 }
 
index 3c734cb6078846aaa7f330bbc13ed71f1f8b215c..7b80adacca8339bbe8dba704a40b339e6534135e 100644 (file)
@@ -39,6 +39,9 @@ constexpr static int DINIT_CP_QUERY_LOAD_MECH = 13;
 // Add a waits for dependency from one service to another, and start the dependency:
 constexpr static int DINIT_CP_ENABLESERVICE = 14;
 
+// Find the name of a service (from a handle)
+constexpr static int DINIT_CP_QUERYSERVICENAME = 15;
+
 // Replies:
 
 // Reply: ACK/NAK to request
@@ -81,6 +84,9 @@ constexpr static int DINIT_RP_LOADER_MECH = 64;
 // Dependent services prevent stopping/restarting. Includes size_t count, handle_t * N handles.
 constexpr static int DINIT_RP_DEPENDENTS = 65;
 
+// Service name:
+constexpr static int DINIT_RP_SERVICENAME = 66;
+
 // Information:
 
 // Service event occurred (4-byte service handle, 1 byte event code)
index 2dae2ccc1b8b744498f6dc05ad4fa0d5ffa0da87..440a2408b10c9963f03870b4438925a82e922b4b 100644 (file)
@@ -146,6 +146,9 @@ class control_conn_t : private service_listener
     // Process an UNLOADSERVICE packet.
     bool process_unload_service();
 
+    // Process a QUERYSERVICENAME packet.
+    bool process_query_name();
+
     // List all loaded services and their state.
     bool list_services();