From c7d6f69a85f04320fff472fcfd41e3837c3631ac Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 5 Feb 2020 15:37:25 +0100 Subject: [PATCH] * Session-id CLI functionality delayed: "lazy evaluation" * From a cli perspective this is a revert to 4.1 behaviour, where the cli does not immediately exit on start if the backend is not running, but with the new session-id function --- CHANGELOG.md | 2 + apps/backend/backend_client.c | 6 +- apps/cli/cli_main.c | 12 +-- lib/clixon/clixon_data.h | 3 +- lib/src/clixon_data.c | 21 ++++-- lib/src/clixon_proto_client.c | 133 ++++++++++++++++++++++++++-------- test/test_sock.sh | 4 +- 7 files changed, 128 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bdc3789..e074d1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ ### Minor changes +* Session-id CLI functionality delayed: "lazy evaluation" + * From a cli perspective this is a revert to 4.1 behaviour, where the cli does not immediately exit on start if the backend is not running, but with the new session-id function * Obsoleted and removed XMLDB format "tree". This function did not work. Only xml and json allowed. * Test framework * Added `-- -S ` command-line to main example to be able to return any state to main example. diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 35cb40bb..79411453 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -1427,11 +1427,15 @@ from_client_hello(clicon_handle h, int retval = -1; uint32_t id; - id = clicon_session_id_get(h); + if (clicon_session_id_get(h, &id) < 0){ + clicon_err(OE_NETCONF, ENOENT, "session_id not set"); + goto done; + } id++; clicon_session_id_set(h, id); cprintf(cbret, "%u", id); retval = 0; + done: return retval; } diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 980988f0..66786725 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -288,7 +288,6 @@ main(int argc, char **argv) char *str; int tabmode; char *dir; - uint32_t id = 0; cvec *nsctx_global = NULL; /* Global namespace context */ /* Defaults */ @@ -607,17 +606,8 @@ main(int argc, char **argv) } /* Go into event-loop unless -1 command-line */ - if (!once){ - /* Send hello request to backend to get session-id back - * This is done once at the beginning of the session and then this is - * used by the client, even though new TCP sessions are created for - * each message sent to the backend. - */ - if (clicon_hello_req(h, &id) < 0) - goto done; - clicon_session_id_set(h, id); + if (!once) retval = cli_interactive(h); - } else retval = 0; done: diff --git a/lib/clixon/clixon_data.h b/lib/clixon/clixon_data.h index a541beac..43d7b934 100644 --- a/lib/clixon/clixon_data.h +++ b/lib/clixon/clixon_data.h @@ -98,7 +98,8 @@ int clicon_xml_changelog_set(clicon_handle h, cxobj *xchlog); int clicon_argv_get(clicon_handle h, int *argc, char ***argv); int clicon_argv_set(clicon_handle h, char *argv0, int argc, char **argv); +/*! Set and get (client/backend) session id */ int clicon_session_id_set(clicon_handle h, uint32_t id); -uint32_t clicon_session_id_get(clicon_handle h); +int clicon_session_id_get(clicon_handle h, uint32_t *id); #endif /* _CLIXON_DATA_H_ */ diff --git a/lib/src/clixon_data.c b/lib/src/clixon_data.c index 2e11bd2b..2436f0b0 100644 --- a/lib/src/clixon_data.c +++ b/lib/src/clixon_data.c @@ -579,19 +579,24 @@ clicon_db_elmnt_set(clicon_handle h, } /*! Get session id - * @param[in] h Clicon handle - * @retval id Session identifier - * Two uses: the backend assigns session-id for clients. + * @param[in] h Clicon handle + * @param[out] sid Session identifier + * @retval 0 OK + * @retval -1 Session id not set + * Session-ids survive TCP sessions that are created for each message sent to the backend. + * The backend assigns session-id for clients: backend assigns, clients get it from backend. */ -uint32_t -clicon_session_id_get(clicon_handle h) +int +clicon_session_id_get(clicon_handle h, + uint32_t *id) { clicon_hash_t *cdat = clicon_data(h); void *p; if ((p = clicon_hash_value(cdat, "session-id", NULL)) == NULL) - return 0; - return *(uint32_t*)p; + return -1; + *id = *(uint32_t*)p; + return 0; } /*! Set session id @@ -599,6 +604,7 @@ clicon_session_id_get(clicon_handle h) * @param[in] id Session id * @retval 0 OK * @retval -1 Error + * Session-ids survive TCP sessions that are created for each message sent to the backend. */ int clicon_session_id_set(clicon_handle h, @@ -609,3 +615,4 @@ clicon_session_id_set(clicon_handle h, clicon_hash_add(cdat, "session-id", &id, sizeof(uint32_t)); return 0; } + diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 03987f4e..102b84cb 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -152,6 +152,34 @@ clicon_rpc_msg(clicon_handle h, return retval; } +/*! Check if there is a valid (cached) session-id. If not, send a hello request to backend + * Session-ids survive TCP sessions that are created for each message sent to the backend. + * Clients use two approaches, either: + * (1) Once at the beginning of the session. Netconf and restconf does this + * (2) First usage, ie "lazy" evaluation when first needed + * @param[in] h clicon handle + * @param[out] session_id Session id + * @retval 0 OK and session_id set + * @retval -1 Error + */ +static int +session_id_check(clicon_handle h, + uint32_t *session_id) +{ + int retval = -1; + uint32_t id; + + if (clicon_session_id_get(h, &id) < 0){ /* Not set yet */ + if (clicon_hello_req(h, &id) < 0) + goto done; + clicon_session_id_set(h, id); + } + retval = 0; + *session_id = id; + done: + return retval; +} + /*! Generic xml netconf clicon rpc * Want to go over to use netconf directly between client and server,... * @param[in] h clicon handle @@ -173,9 +201,12 @@ clicon_rpc_netconf(clicon_handle h, int *sp) { int retval = -1; + uint32_t session_id; struct clicon_msg *msg = NULL; - if ((msg = clicon_msg_encode(clicon_session_id_get(h), "%s", xmlstr)) < 0) + if (session_id_check(h, &session_id) < 0) + goto done; + if ((msg = clicon_msg_encode(session_id, "%s", xmlstr)) < 0) goto done; if (clicon_rpc_msg(h, msg, xret, sp) < 0) goto done; @@ -304,7 +335,10 @@ clicon_rpc_get_config(clicon_handle h, cxobj *xd; cg_var *cv = NULL; char *prefix; + uint32_t session_id; + if (session_id_check(h, &session_id) < 0) + goto done; if ((cb = cbuf_new()) == NULL) goto done; cprintf(cb, ""); } cprintf(cb, ""); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), - "%s", cbuf_get(cb))) == NULL) + if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) goto done; @@ -382,7 +415,10 @@ clicon_rpc_edit_config(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; if ((cb = cbuf_new()) == NULL) goto done; cprintf(cb, ""); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), - "%s", cbuf_get(cb))) == NULL) + if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) goto done; @@ -438,10 +473,13 @@ clicon_rpc_copy_config(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), - "<%s/><%s/>", + if ((msg = clicon_msg_encode(session_id, + "<%s/><%s/>", username?username:"", db1, db2)) == NULL) goto done; @@ -479,9 +517,12 @@ clicon_rpc_delete_config(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "<%s/>none", username?username:"", db)) == NULL) goto done; @@ -515,9 +556,12 @@ clicon_rpc_lock(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "<%s/>", username?username:"", db)) == NULL) goto done; @@ -551,9 +595,12 @@ clicon_rpc_unlock(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "<%s/>", username?username:"", db)) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) @@ -620,7 +667,10 @@ clicon_rpc_get(clicon_handle h, char *username; cg_var *cv = NULL; char *prefix; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; if ((cb = cbuf_new()) == NULL) goto done; cprintf(cb, ""); } cprintf(cb, ""); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) @@ -691,9 +741,12 @@ clicon_rpc_close_session(clicon_handle h) cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "", username?username:"")) == NULL) goto done; @@ -727,9 +780,12 @@ clicon_rpc_kill_session(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t my_session_id; /* Not the one to kill */ + + if (session_id_check(h, &my_session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(my_session_id, "%u", username?username:"", session_id)) == NULL) goto done; @@ -763,9 +819,12 @@ clicon_rpc_validate(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "<%s/>", username?username:"", db)) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) @@ -796,9 +855,12 @@ clicon_rpc_commit(clicon_handle h) cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "", username?username:"")) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) @@ -829,9 +891,12 @@ clicon_rpc_discard_changes(clicon_handle h) cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "", username?username:"")) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) @@ -870,9 +935,12 @@ clicon_rpc_create_subscription(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "" "%s" "" @@ -910,9 +978,12 @@ clicon_rpc_debug(clicon_handle h, cxobj *xret = NULL; cxobj *xerr; char *username; - + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; username = clicon_username_get(h); - if ((msg = clicon_msg_encode(clicon_session_id_get(h), + if ((msg = clicon_msg_encode(session_id, "%d", username?username:"", level)) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) diff --git a/test/test_sock.sh b/test/test_sock.sh index dd6d8941..ba92de51 100755 --- a/test/test_sock.sh +++ b/test/test_sock.sh @@ -64,10 +64,10 @@ EOF expectfn "$clixon_cli -1f $cfg show version" 0 "$version." new "hello session-id 2" - expecteof "$clixon_util_socket -a $family -s $sock -D $DBG" 0 "" "2" + expecteof "$clixon_util_socket -a $family -s $sock -D $DBG" 0 "" "3" new "hello session-id 2" - expecteof "$clixon_util_socket -a $family -s $sock -D $DBG" 0 "" "3" + expecteof "$clixon_util_socket -a $family -s $sock -D $DBG" 0 "" "4" if [ $BE -ne 0 ]; then new "Kill backend"