From ac01dc0e6817679c114d6e118a28c77aa948af6e Mon Sep 17 00:00:00 2001 From: Blair Steven Date: Mon, 30 Sep 2024 14:49:58 +1300 Subject: [PATCH] Break up compound non-root keys Code in apteryxd is designed to handle GNode keys as single key values, so encode the tree in this way. --- rpc.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/rpc.c b/rpc.c index 4f2b879..05eb47e 100644 --- a/rpc.c +++ b/rpc.c @@ -935,41 +935,100 @@ rpc_msg_decode_string (rpc_message msg) return value; } +static void rpc_msg_encode_tree_full (rpc_message msg, GNode *root, bool break_key); + static void rpc_msg_add_children (rpc_message msg, GNode *root) { GNode *child = NULL; /* If there are any children, write them here. */ - if (g_node_first_child(root)) + if (g_node_first_child (root)) { rpc_msg_encode_uint8 (msg, rpc_start_children); - for (child = g_node_first_child(root); child; child = g_node_next_sibling(child)) + for (child = g_node_first_child (root); child; child = g_node_next_sibling (child)) { - rpc_msg_encode_tree (msg, child); + rpc_msg_encode_tree_full (msg, child, true); } rpc_msg_encode_uint8 (msg, rpc_end_children); } } -void -rpc_msg_encode_tree (rpc_message msg, GNode *root) +static void +rpc_msg_encode_tree_full (rpc_message msg, GNode *root, bool break_key) { const char *key = APTERYX_NAME (root); const char *value = APTERYX_HAS_VALUE (root) ? APTERYX_VALUE (root) : NULL; - rpc_msg_encode_uint8 (msg, rpc_value); - /* Write this key (and value). */ - rpc_msg_encode_string (msg, key); - rpc_msg_encode_string (msg, value ?: ""); + if (break_key && strchr (key, '/')) + { + char *broken_key = g_strdup (key); + char *end; + char *chunk = broken_key; + int extra_nodes = 0; + + while ((end = strchr (chunk, '/')) != NULL) + { + /* Truncate at the first slash */ + *end = '\0'; + + /* This is an intermediate node, so we don't ever want to + * print the value attached to the end, just the first bit of + * the key. + */ + rpc_msg_encode_uint8 (msg, rpc_value); + rpc_msg_encode_string (msg, chunk); + rpc_msg_encode_string (msg, ""); + + /* We are going to need to close exactly this many children nodes + * at the end of the loop, so keep count. + */ + extra_nodes++; + rpc_msg_encode_uint8 (msg, rpc_start_children); + + /* Skip past the null terminator */ + chunk = end + 1; + } + + /* Write the end of the key and the value (if any.) */ + rpc_msg_encode_uint8 (msg, rpc_value); + rpc_msg_encode_string (msg, chunk); + rpc_msg_encode_string (msg, value ?: ""); + g_free (broken_key); + + /* If this node has no value, add its children. */ + if (!APTERYX_HAS_VALUE (root)) + { + rpc_msg_add_children (msg, root); + } - /* If this node has no value, add its children. */ - if (!APTERYX_HAS_VALUE (root)) + /* Close all the children opened when breaking up the key */ + while (extra_nodes--) + { + rpc_msg_encode_uint8 (msg, rpc_end_children); + } + } + else { - rpc_msg_add_children (msg, root); + rpc_msg_encode_uint8 (msg, rpc_value); + /* Write this key (and value). */ + rpc_msg_encode_string (msg, key); + rpc_msg_encode_string (msg, value ?: ""); + + /* If this node has no value, add its children. */ + if (!APTERYX_HAS_VALUE (root)) + { + rpc_msg_add_children (msg, root); + } } } +void +rpc_msg_encode_tree (rpc_message msg, GNode *root) +{ + rpc_msg_encode_tree_full (msg, root, false); +} + static GNode * _rpc_msg_decode_tree (rpc_message msg, GNode *root) {