dbus - 两个用户之间的 DBUS 通信
问题描述
不幸的是,关于 dbus 通信的信息很少。有谁知道,如何在同一个linux上完成两个用户之间的通信?应该注意哪些事项?应该使用什么类型的 dbus(会话或系统)?
解决方案
谢谢@Anton,我现在明白会话总线必须满足两个条件:相同的 uid 和相同的会话总线。目前,我尝试通过系统 D-bus 建立两个用户之间的通信,但显然我做错了。
/etc/dbus-1/system.d/test_bus.conf
<!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="user">
<allow own="com.test.Bus"/>
<allow send_destination="com.test.Bus"/>
<allow send_interface="com.test.Bus"/>
<allow receive_sender="com.test.Bus"/>
</policy>
<policy user="user2">
<allow own="com.test.Bus"/>
<allow send_destination="com.test.Bus"/>
<allow send_interface="com.test.Bus"/>
<allow receive_sender="com.test.Bus"/>
</policy>
</busconfig>
服务器.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
#include <dbus/dbus.h>
const char* const INTERFACE_NAME = "com.test.Bus";
const char* const SERVER_BUS_NAME = "com.test.Bus";
const char* const OBJECT_PATH_NAME = "/server";
const char* const METHOD_NAME = "add_numbers";
DBusError dbus_error;
void print_dbus_error(char* str);
bool isinteger(char* ptr);
int main(int argc, char** argv)
{
DBusConnection* conn;
int ret;
dbus_error_init(&dbus_error);
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
printf("Con name=%s\n", dbus_bus_get_unique_name(conn)); // my
if (dbus_error_is_set(&dbus_error))
print_dbus_error("dbus_bus_get");
if (!conn)
exit(1);
// Get a well known name
ret = dbus_bus_request_name(conn, SERVER_BUS_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
if (dbus_error_is_set(&dbus_error))
print_dbus_error("dbus_bus_get");
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
fprintf(stderr, "Dbus: not primary owner, ret = %d\n", ret);
exit(1);
}
// Handle request from clients
while (1)
{
// Block for msg from client
if (!dbus_connection_read_write_dispatch(conn, -1))
{
fprintf(stderr, "Not connected now.\n");
exit(1);
}
DBusMessage* message;
if ((message = dbus_connection_pop_message(conn)) == NULL)
{
fprintf(stderr, "Did not get message\n");
continue;
}
if (dbus_message_is_method_call(message, INTERFACE_NAME, METHOD_NAME))
{
char* s;
char * str1 = NULL, *str2 = NULL;
const char space[4] = " \n\t";
long i, j;
bool error = false;
if (dbus_message_get_args(message, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID))
{
printf("%s", s);
// Validate received message
str1 = strtok(s, space);
if (str1)
str2 = strtok(NULL, space);
if (!str1 || !str2)
error = true;
if (!error)
{
if (isinteger(str1))
i = atol(str1);
else
error = true;
}
if (!error)
{
if (isinteger(str2))
j = atol(str2);
else
error = true;
}
if (!error)
{
// send reply
DBusMessage* reply;
char answer[40];
sprintf(answer, "Sum is %ld", i + j);
if ((reply = dbus_message_new_method_return(message)) == NULL)
{
fprintf(stderr, "Error in dbus_message_new_method_return\n");
exit(1);
}
DBusMessageIter iter;
dbus_message_iter_init_append(reply, &iter);
char* ptr = answer;
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ptr))
{
fprintf(stderr, "Error in dbus_message_iter_append_basic\n");
exit(1);
}
if (!dbus_connection_send(conn, reply, NULL))
{
fprintf(stderr, "Error in dbus_connection_send\n");
exit(1);
}
dbus_connection_flush(conn);
dbus_message_unref(reply);
}
else // There was an error
{
DBusMessage* dbus_error_msg;
char error_msg[] = "Error in input";
if ((dbus_error_msg = dbus_message_new_error(message, DBUS_ERROR_FAILED, error_msg)) == NULL)
{
fprintf(stderr, "Error in dbus_message_new_error\n");
exit(1);
}
if (!dbus_connection_send(conn, dbus_error_msg, NULL))
{
fprintf(stderr, "Error in dbus_connection_send\n");
exit(1);
}
dbus_connection_flush(conn);
dbus_message_unref(dbus_error_msg);
}
}
else
{
print_dbus_error("Error getting message");
}
}
}
return 0;
}
bool isinteger(char* ptr)
{
if (*ptr == '+' || *ptr == '-')
ptr++;
while (*ptr)
{
if (!isdigit((int)*ptr++))
return false;
}
return true;
}
void print_dbus_error(char* str)
{
fprintf(stderr, "%s: %s\n", str, dbus_error.message);
dbus_error_free(&dbus_error);
}
客户端.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <dbus/dbus.h>
const char* const INTERFACE_NAME = "com.test.Bus";
const char* const SERVER_BUS_NAME = "com.test.Bus";
const char* const CLIENT_BUS_NAME = "com.test.Bus";
const char* const SERVER_OBJECT_PATH_NAME = "/server";
const char* const CLIENT_OBJECT_PATH_NAME = "/client";
const char* const METHOD_NAME = "add_numbers";
DBusError dbus_error;
void print_dbus_error(char* str);
int main(int argc, char** argv)
{
DBusConnection* conn;
int ret;
char input[80];
dbus_error_init(&dbus_error);
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
printf("Con name=%s\n", dbus_bus_get_unique_name(conn)); // my
if (dbus_error_is_set(&dbus_error))
print_dbus_error("dbus_bus_get");
if (!conn)
exit(1);
printf("Please type two numbers: ");
while (fgets(input, 78, stdin) != NULL)
{
// Get a well known name
while (1)
{
ret = dbus_bus_request_name(conn, CLIENT_BUS_NAME, 0, &dbus_error);
if (ret == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
break;
if (ret == DBUS_REQUEST_NAME_REPLY_IN_QUEUE)
{
fprintf(stderr, "Waiting for the bus ... \n");
sleep(1);
continue;
}
if (dbus_error_is_set(&dbus_error))
print_dbus_error("dbus_bus_get");
}
DBusMessage* request;
if ((request = dbus_message_new_method_call(SERVER_BUS_NAME, SERVER_OBJECT_PATH_NAME, INTERFACE_NAME,
METHOD_NAME)) == NULL)
{
fprintf(stderr, "Error in dbus_message_new_method_call\n");
exit(1);
}
DBusMessageIter iter;
dbus_message_iter_init_append(request, &iter);
char* ptr = input;
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ptr))
{
fprintf(stderr, "Error in dbus_message_iter_append_basic\n");
exit(1);
}
DBusPendingCall* pending_return;
if (!dbus_connection_send_with_reply(conn, request, &pending_return, -1))
{
fprintf(stderr, "Error in dbus_connection_send_with_reply\n");
exit(1);
}
if (pending_return == NULL)
{
fprintf(stderr, "pending return is NULL");
exit(1);
}
dbus_connection_flush(conn);
dbus_message_unref(request);
dbus_pending_call_block(pending_return);
DBusMessage* reply;
if ((reply = dbus_pending_call_steal_reply(pending_return)) == NULL)
{
fprintf(stderr, "Error in dbus_pending_call_steal_reply");
exit(1);
}
dbus_pending_call_unref(pending_return);
char* s;
if (dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID))
{
printf("%s\n", s);
}
else
{
fprintf(stderr, "Did not get arguments in reply\n");
exit(1);
}
dbus_message_unref(reply);
if (dbus_bus_release_name(conn, CLIENT_BUS_NAME, &dbus_error) == -1)
{
fprintf(stderr, "Error in dbus_bus_release_name\n");
exit(1);
}
printf("Please type two numbers: ");
}
return 0;
}
void print_dbus_error(char* str)
{
fprintf(stderr, "%s: %s\n", str, dbus_error.message);
dbus_error_free(&dbus_error);
}
生成文件
all: serverDBUS clientDBUS
%.o: %.c
gcc -Wall -c $< `pkg-config --cflags dbus-1`
serverDBUS: server.o
gcc server.o -o serverDBUS `pkg-config --libs dbus-1`
clientDBUS: client.o
gcc client.o -o clientDBUS `pkg-config --libs dbus-1`
.PHONY: clean
clean:
rm *.o serverDBUS clientDBUS
推荐阅读
- python - 在python 2.7中对大数进行幂运算后长整数是错误的
- javascript - 即使我在 2 个不同的范围内声明变量,为什么仍然存在重复错误?
- javascript - Javascript fetch - 读取错误的请求响应时遇到问题
- swift - CollectionViewCell 返回表达式类型错误
- python - 使用在 python 2 中腌制的 python 3 取消腌制文件
- javascript - JS获取数组子节点数据
- jupyter-notebook - 启动 jupyter-lab 并从命令行打开一个特定的笔记本?
- sql - 报表生成器中的 URL 连接
- typescript - 不和谐嵌入加入消息
- php - 如何在php的同一张表中插入同名数据?