Reputation: 341
I am using the sdbus-cpp libary to test how to create a service and access it's methods and signals through a D-Bus client. The library provides an example of this that I tested and worked for me. However, this example creates a service in the session bus and I would like to make it work on the system bus. This is the example:
Server side:
#include <sdbus-c++/sdbus-c++.h>
#include <vector>
#include <string>
int main(int argc, char *argv[])
{
// Create D-Bus connection to the (either system or session) bus and requests a well-known name on it.
sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"};
auto connection = sdbus::createBusConnection(serviceName);
// Create concatenator D-Bus object.
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenator = sdbus::createObject(*connection, std::move(objectPath));
auto concatenate = [&concatenator](const std::vector<int> numbers, const std::string& separator)
{
// Return error if there are no numbers in the collection
if (numbers.empty())
throw sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.Concatenator.Error"}, "No numbers provided");
std::string result;
for (auto number : numbers)
{
result += (result.empty() ? std::string() : separator) + std::to_string(number);
}
// Emit 'concatenated' signal
concatenator->emitSignal("concatenated").onInterface("org.sdbuscpp.Concatenator").withArguments(result);
std::cout << "Signal emitted with result: " << result << std::endl;
return result;
};
// Register D-Bus methods and signals on the concatenator object, and exports the object.
concatenator->addVTable(sdbus::registerMethod("concatenate").implementedAs(std::move(concatenate)),
sdbus::registerSignal("concatenated").withParameters<std::string>())
.forInterface("org.sdbuscpp.Concatenator");
// Run the loop on the connection.
connection->enterEventLoop();
}
Client side:
#include <sdbus-c++/sdbus-c++.h>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>
void onConcatenated(const std::string& concatenatedString)
{
std::cout << "Received signal with concatenated string " << concatenatedString << std::endl;
}
int main(int argc, char *argv[])
{
// Create proxy object for the concatenator object on the server side
sdbus::ServiceName destination{"org.sdbuscpp.concatenator"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenatorProxy = sdbus::createProxy(std::move(destination), std::move(objectPath));
// Let's subscribe for the 'concatenated' signals
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
concatenatorProxy->uponSignal("concatenated").onInterface(interfaceName).call([](const std::string& str){ onConcatenated(str); });
std::cout << "Signal handler registered." << std::endl;
std::vector<int> numbers = {1, 2, 3};
std::string separator = ":";
// Invoke concatenate on given interface of the object
{
std::string concatenatedString;
concatenatorProxy->callMethod("concatenate").onInterface(interfaceName).withArguments(numbers, separator).storeResultsTo(concatenatedString);
assert(concatenatedString == "1:2:3");
std::cout << "Methode result assert: " << concatenatedString << std::endl;
}
// Invoke concatenate again, this time with no numbers and we shall get an error
{
try
{
concatenatorProxy->callMethod("concatenate").onInterface(interfaceName).withArguments(std::vector<int>(), separator);
assert(false);
}
catch(const sdbus::Error& e)
{
std::cerr << "Got concatenate error " << e.getName() << " with message " << e.getMessage() << std::endl;
}
}
// Give sufficient time to receive 'concatenated' signal from the first concatenate invocation
sleep(2);
return 0;
}
To test the example I execute the client and the server in two separate terminals. This is the output of both client and server. They work as expected:
Then, to test this same example in the system bus, for starters I already created a policy file in /etc/dbus-1/system.d
that looks like this:
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="me">
<allow own="org.sdbuscpp.concatenator"/>
<allow send_destination="org.sdbuscpp.concatenator"/>
<allow send_interface="org.sdbuscpp.Concatenator" send_type="method_call"/>
<allow send_interface="org.sdbuscpp.Concatenator" send_type="signal"/>
<allow receive_sender="org.sdbuscpp.concatenator"/>
<allow receive_type="signal"/>
</policy>
</busconfig>
The problem I am having is that the client is not detecting the signal generated by the server when testing this in the system bus. However, it works in the session bus. And I am sure the method executed by the client is reaching the server because I print the data received by the server and it's correct ("1:2:3").
I am not sure what am I doing wrong, am I lacking some permit in the policy file? I also tried changing the policy line to but was getting the same issue. Do I also need to provide a .service file in /etc/systemd/system? Doesn't look like it by my understanding.
I also tried using this more generic policy file with the same results:
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="me">
<allow own="org.sdbuscpp.concatenator"/>
</policy>
<policy context="default">
<allow send_destination="org.sdbuscpp.concatenator" send_interface="org.sdbuscpp.Concatenator"/>
</policy>
</busconfig>
Here are the changes I did to the client and server from the example, to try using them in the system bus. Basically just specified that the connection should be to the system bus:
Client side:
auto connection = sdbus::createSystemBusConnection();
sdbus::ServiceName destination{"org.sdbuscpp.concatenator"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenatorProxy = sdbus::createProxy(*connection, std::move(destination), std::move(objectPath));
Server side:
sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"};
auto connection = sdbus::createSystemBusConnection(serviceName);
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenator = sdbus::createObject(*connection, std::move(objectPath));
Again, I execute the client and the server in two separate terminals. This is the output of both client and server. As you can see the string "Received signal with concatenated string 1:2:3" is not being shown this time, meaning the client didn't detect the signal triggering:
Upvotes: 3
Views: 113