libnetconf C++: add support for user RPCs

The API is rather straightforward, it takes a string. I experimented
with consuming a libyang data node instead, but this kept failing
because I was naively creating nodes from a different libyang context,
and that always resulted in an error.

Now, given that the edit-config method already takes a string, let's
make our lives easier and work on this via strings.

Change-Id: I35467dece535df41e223013e32500596d272560c
diff --git a/src/netconf-client.cpp b/src/netconf-client.cpp
index a761bb4..8f0e2ec 100644
--- a/src/netconf-client.cpp
+++ b/src/netconf-client.cpp
@@ -365,6 +365,21 @@
     impl::do_rpc_ok(this, std::move(rpc));
 }
 
+std::shared_ptr<libyang::Data_Node> Session::rpc(const std::string& xmlData)
+{
+    auto rpc = impl::guarded(nc_rpc_act_generic_xml(xmlData.c_str(), NC_PARAMTYPE_CONST));
+    if (!rpc) {
+        throw std::runtime_error("Cannot create generic RPC");
+    }
+    auto reply = impl::do_rpc_data_or_ok(this, std::move(rpc));
+    if (reply) {
+        auto dataNode = libyang::create_new_Data_Node((*reply)->data);
+        return dataNode->dup_withsiblings(1);
+    } else {
+        return nullptr;
+    }
+}
+
 ReportedError::ReportedError(const std::string& what)
     : std::runtime_error(what)
 {
diff --git a/src/netconf-client.h b/src/netconf-client.h
index 1923e71..b9a1925 100644
--- a/src/netconf-client.h
+++ b/src/netconf-client.h
@@ -43,6 +43,7 @@
                     const NC_RPC_EDIT_ERROPT errorOption,
                     const std::string& data);
     void copyConfigFromString(const NC_DATASTORE target, const std::string& data);
+    std::shared_ptr<libyang::Data_Node> rpc(const std::string& xmlData);
     void commit();
     void discard();
     struct nc_session* session_internal(); // FIXME: remove me