Compare commits
505 Commits
dev
...
dev-backup
| Author | SHA1 | Date |
|---|---|---|
|
|
81bfb81dc7 | |
|
|
ab059a1a6f | |
|
|
4d574f5114 | |
|
|
27eaec3a64 | |
|
|
da7dce2276 | |
|
|
f168d0a538 | |
|
|
11f44f733a | |
|
|
6b596e4ff5 | |
|
|
9d294a428a | |
|
|
5b2a21530c | |
|
|
33af11c421 | |
|
|
4e1f285645 | |
|
|
b14b9c389c | |
|
|
e2311361b8 | |
|
|
fc8cd0c944 | |
|
|
8617569b6b | |
|
|
e5b7998e75 | |
|
|
81bf130027 | |
|
|
ba9f08a713 | |
|
|
a7d2c908d3 | |
|
|
68316d5269 | |
|
|
78c43330e9 | |
|
|
ac19b907f1 | |
|
|
56d9f4f858 | |
|
|
74b75590cb | |
|
|
b1bb85ad39 | |
|
|
22572fa2f1 | |
|
|
fc535ac9a7 | |
|
|
7a94a96240 | |
|
|
dad95e2787 | |
|
|
8c2b7f8a4e | |
|
|
fd01781f55 | |
|
|
ed778af5a9 | |
|
|
4ec33c844e | |
|
|
4c070d84b0 | |
|
|
dc15b3f58b | |
|
|
3a898cb303 | |
|
|
78f2846dd1 | |
|
|
659b244934 | |
|
|
1da41823bb | |
|
|
f96515434f | |
|
|
daf0204ba9 | |
|
|
749a14fb69 | |
|
|
d0dbef6f1d | |
|
|
3362b52de2 | |
|
|
586a2cda63 | |
|
|
f28493904c | |
|
|
032f1f858f | |
|
|
b22c42a889 | |
|
|
01dde63642 | |
|
|
1d221149c8 | |
|
|
a2858e3dfc | |
|
|
0701595849 | |
|
|
a274cb1651 | |
|
|
43e35964c3 | |
|
|
c9d0c2f82d | |
|
|
0974feba8e | |
|
|
cfb155730d | |
|
|
340bd6613e | |
|
|
cfda376446 | |
|
|
1b0af71102 | |
|
|
870af45893 | |
|
|
4057b8981f | |
|
|
87e7aeb429 | |
|
|
3d293393c5 | |
|
|
52f0b2de34 | |
|
|
89180702ef | |
|
|
a64bdce895 | |
|
|
1b3ed4a5ac | |
|
|
46435e4b40 | |
|
|
e3ce03e6ad | |
|
|
13481a4cd5 | |
|
|
2b334c10d7 | |
|
|
d2b17914ed | |
|
|
de90faf2e7 | |
|
|
5628656716 | |
|
|
042d7d9f36 | |
|
|
ad8d2597e6 | |
|
|
0e595320ab | |
|
|
b3f60356d8 | |
|
|
5a6ae3f70a | |
|
|
d1f6afe13a | |
|
|
32f6cc0549 | |
|
|
301998ea83 | |
|
|
e842fa444a | |
|
|
85de640853 | |
|
|
d959b76294 | |
|
|
2d72c6a7ce | |
|
|
ec9aa1794c | |
|
|
39e08271d4 | |
|
|
3a8a321d4e | |
|
|
bdf531019c | |
|
|
ca9e7d624c | |
|
|
98afab50c0 | |
|
|
60c38e022f | |
|
|
589b535c75 | |
|
|
bbf0241519 | |
|
|
351f0454c8 | |
|
|
ecb3d6bed5 | |
|
|
a07e973574 | |
|
|
5a83196f1d | |
|
|
c315121abf | |
|
|
43e1c9b33a | |
|
|
cad5f9a52a | |
|
|
0d07b93011 | |
|
|
256d0a4f1f | |
|
|
38fdc66612 | |
|
|
837fcbb4b5 | |
|
|
50dd8937e9 | |
|
|
780614cd9d | |
|
|
2fc25fcc54 | |
|
|
5d95e3a9d2 | |
|
|
c6900c902d | |
|
|
3da2f6b4d5 | |
|
|
dec3c49ca4 | |
|
|
c36fb62273 | |
|
|
abbbffa922 | |
|
|
8837aa44bd | |
|
|
38c863df46 | |
|
|
3a75d71df9 | |
|
|
53bf3e7fd8 | |
|
|
741932da37 | |
|
|
ca08b62bfc | |
|
|
f0787a21ef | |
|
|
8f6f01ae23 | |
|
|
14307399b1 | |
|
|
eb1bcb28b7 | |
|
|
1f2d4109c8 | |
|
|
5d7b8476fd | |
|
|
1c48274b13 | |
|
|
3906389b88 | |
|
|
6cce5b24f1 | |
|
|
f755596ba2 | |
|
|
42769586a9 | |
|
|
e84ea52cd1 | |
|
|
1f4cc057d1 | |
|
|
011277f8dd | |
|
|
63234d6d24 | |
|
|
9a03af414d | |
|
|
4ae79fdc0e | |
|
|
538d155110 | |
|
|
a0d217d9d5 | |
|
|
df25b39a1e | |
|
|
922929e6ca | |
|
|
123016bb6c | |
|
|
a711f560cf | |
|
|
7c533cd68c | |
|
|
f57701ee79 | |
|
|
c52a822b49 | |
|
|
d5ee442b35 | |
|
|
2b55cb408b | |
|
|
5c8862b1e0 | |
|
|
d59e246ac9 | |
|
|
7bb83eb141 | |
|
|
cd00843d95 | |
|
|
84cbd352a7 | |
|
|
6cf17ba1cc | |
|
|
6af0b987fa | |
|
|
3854b4a7f4 | |
|
|
6857500e2f | |
|
|
2b5bcd4b18 | |
|
|
6f4746bc49 | |
|
|
9c24729a48 | |
|
|
acdd224a19 | |
|
|
77a691d476 | |
|
|
99415b2b1c | |
|
|
56592a57bf | |
|
|
8c65ef7f65 | |
|
|
b572ba5216 | |
|
|
b854979073 | |
|
|
9a524577b0 | |
|
|
156f8c72bf | |
|
|
380ee90b2d | |
|
|
82a9c0b5f2 | |
|
|
8fbd2ec0c9 | |
|
|
67b57fbff7 | |
|
|
1fc1c07c3d | |
|
|
373a7a856f | |
|
|
969f21eca4 | |
|
|
47341f1878 | |
|
|
3571298c49 | |
|
|
f547545e8c | |
|
|
b121603315 | |
|
|
a991b6e0d9 | |
|
|
a9b1f90a29 | |
|
|
c82af41ced | |
|
|
b0f7382e65 | |
|
|
15551b602c | |
|
|
45ab428a01 | |
|
|
2b7bb6639b | |
|
|
6b990db97c | |
|
|
ecff015e0b | |
|
|
bbbf8a6575 | |
|
|
1f6be796da | |
|
|
f88a3186fb | |
|
|
930a034820 | |
|
|
360e1f3422 | |
|
|
795f529669 | |
|
|
1d2f134d77 | |
|
|
21e521aab5 | |
|
|
5123353f75 | |
|
|
f1f079a03a | |
|
|
f57229a71c | |
|
|
81e370dca4 | |
|
|
5415101d00 | |
|
|
1bbde9ca87 | |
|
|
7b42da75e7 | |
|
|
6e577247af | |
|
|
eddfa1fc63 | |
|
|
bfcccef026 | |
|
|
5ae81a0eb9 | |
|
|
08b1e87b31 | |
|
|
723467c703 | |
|
|
9cd358432a | |
|
|
cdb3c9572a | |
|
|
edff96484c | |
|
|
b2c8718e45 | |
|
|
21a2544c9d | |
|
|
337f1b31bb | |
|
|
2df131ce0d | |
|
|
686fc26441 | |
|
|
282235f941 | |
|
|
739ae6ef26 | |
|
|
213fed6add | |
|
|
0465d86991 | |
|
|
4c125d6ad5 | |
|
|
9463f0ab3c | |
|
|
bc4c2efd74 | |
|
|
b8862d34d3 | |
|
|
d48d0a4b3e | |
|
|
b9540df318 | |
|
|
93e6a09726 | |
|
|
0c5a311077 | |
|
|
e54a8ccf7b | |
|
|
5f07e053e8 | |
|
|
190b579c01 | |
|
|
05bd22dfb6 | |
|
|
307e4132eb | |
|
|
f2b00d18b6 | |
|
|
cabe78d7a6 | |
|
|
d57b1979d5 | |
|
|
3564bc897f | |
|
|
640c13a7da | |
|
|
ea704f767b | |
|
|
9f71038908 | |
|
|
24a199849e | |
|
|
f0cc3f1a51 | |
|
|
f6328ee282 | |
|
|
5533e47eef | |
|
|
1e875eee5c | |
|
|
0d9a354d5e | |
|
|
344b724082 | |
|
|
8585f8dafc | |
|
|
50a8e5b3e3 | |
|
|
b8757ac11d | |
|
|
b02c416e7e | |
|
|
f0655f8b0f | |
|
|
efcaeb68c0 | |
|
|
251c7c08b5 | |
|
|
0697bc24e9 | |
|
|
9a0702bccb | |
|
|
e9317d35ea | |
|
|
7564954162 | |
|
|
9303ef8a16 | |
|
|
41f8504c6c | |
|
|
727c8ef15d | |
|
|
d79816cdf0 | |
|
|
0cfd7e7442 | |
|
|
b698b288cf | |
|
|
08bc2fca82 | |
|
|
e1fc5e77f5 | |
|
|
f95e6a90e8 | |
|
|
045f081101 | |
|
|
7129b56fbc | |
|
|
abe73a67dc | |
|
|
d599968b1e | |
|
|
014b4b8d15 | |
|
|
d61a3d45d1 | |
|
|
da5bc70d74 | |
|
|
c3226b8206 | |
|
|
5a5c810bc9 | |
|
|
6409610b7e | |
|
|
1efcc10131 | |
|
|
4af3a499b6 | |
|
|
37869d91db | |
|
|
3ec486e4bf | |
|
|
1e8bff6d19 | |
|
|
d7bcab298b | |
|
|
e8c3ce5bc8 | |
|
|
47c7738b3f | |
|
|
e254b4b208 | |
|
|
d5b39ecf8c | |
|
|
c32337cef6 | |
|
|
6d6169eb12 | |
|
|
f8d73e3b7d | |
|
|
73c593eed7 | |
|
|
463be0e5b2 | |
|
|
36bcc4b2d2 | |
|
|
7ce811eef0 | |
|
|
975a24a1ff | |
|
|
960d2d27e9 | |
|
|
1bac6977af | |
|
|
47c19efa16 | |
|
|
5725e97799 | |
|
|
7f639bef49 | |
|
|
94e8a5c67d | |
|
|
5dfbb88b9c | |
|
|
c28afe1653 | |
|
|
4f094c0501 | |
|
|
31d6d4f894 | |
|
|
5ac1a6b233 | |
|
|
a7c96b96c2 | |
|
|
0a70554054 | |
|
|
00c7da7fc9 | |
|
|
4ae1ce7ded | |
|
|
aea656b090 | |
|
|
3ddfc598f9 | |
|
|
51203d47e4 | |
|
|
4b10a2cfe5 | |
|
|
71f621a95c | |
|
|
a7c003c6b7 | |
|
|
208aefa1ef | |
|
|
e29fc301fd | |
|
|
ae55d45e07 | |
|
|
84b932d339 | |
|
|
9030b519c2 | |
|
|
395189ff75 | |
|
|
beeef8d9cb | |
|
|
157de75d42 | |
|
|
62ebc7d37c | |
|
|
0f0a0dce2d | |
|
|
9e099e075e | |
|
|
eef1408e83 | |
|
|
1b68bd5d37 | |
|
|
9bd8b008c6 | |
|
|
b5ceca251a | |
|
|
67de7dd271 | |
|
|
5c72b8193c | |
|
|
e9707aca9f | |
|
|
919e7b744b | |
|
|
5d9ea53b75 | |
|
|
1b87eea590 | |
|
|
0a73d922c9 | |
|
|
f77d9dfee6 | |
|
|
242b93d85c | |
|
|
57ddacceef | |
|
|
f96b27a7e5 | |
|
|
fba30b4954 | |
|
|
84bde444d7 | |
|
|
4a60e27e0f | |
|
|
3378e10c7c | |
|
|
799db28a3f | |
|
|
b7dbb506b0 | |
|
|
2cb42ddf36 | |
|
|
7869a8b0a3 | |
|
|
b7f18b4658 | |
|
|
97261500ac | |
|
|
3118967460 | |
|
|
3f2a1322e2 | |
|
|
2769107430 | |
|
|
123ea2203f | |
|
|
21f789b8d7 | |
|
|
ba7aad615c | |
|
|
5ff12d0e8f | |
|
|
02a0d1c308 | |
|
|
467c3e623e | |
|
|
2cb8f33a03 | |
|
|
38f7261caa | |
|
|
5a0ad136bc | |
|
|
9025385a6e | |
|
|
74035750e2 | |
|
|
2705df8945 | |
|
|
06c06dc150 | |
|
|
1e5736a769 | |
|
|
a0df1f3a4f | |
|
|
5286617d17 | |
|
|
7d7f73e130 | |
|
|
23c299dc3f | |
|
|
98d6b5b96d | |
|
|
2652feabc2 | |
|
|
42bdabbefc | |
|
|
f8a650ab98 | |
|
|
95858d5190 | |
|
|
842be382da | |
|
|
e862047d9d | |
|
|
6ac941b099 | |
|
|
a1f4514a5a | |
|
|
06c6a3d60c | |
|
|
d0507d99dc | |
|
|
67c13e1b1e | |
|
|
13262739f5 | |
|
|
98bf2e3926 | |
|
|
262ee738bd | |
|
|
8c1b9c9e6d | |
|
|
5de73c0ce4 | |
|
|
01fad8f214 | |
|
|
72a2c6d38d | |
|
|
fe3f118681 | |
|
|
2b1a7bed35 | |
|
|
3e7be8ffd5 | |
|
|
7909aade9c | |
|
|
bc04b2b674 | |
|
|
cd32f0d4c9 | |
|
|
5929f451fd | |
|
|
178caf3bf3 | |
|
|
e8004dcc51 | |
|
|
33ddb45199 | |
|
|
82487204bb | |
|
|
c88da8f4fb | |
|
|
a06c2bf95e | |
|
|
41a68a1704 | |
|
|
80a40e4bc1 | |
|
|
8c20dd4094 | |
|
|
ae9735d8ec | |
|
|
b0842bfd31 | |
|
|
c008c770d3 | |
|
|
3645f00aec | |
|
|
7aebce13e4 | |
|
|
4e2ff8a42d | |
|
|
b8094a462a | |
|
|
fa8baad6b0 | |
|
|
5cc51c7078 | |
|
|
a34894b7da | |
|
|
aca2ce7cb6 | |
|
|
1c4c651c63 | |
|
|
a446318b57 | |
|
|
011f5c8ca9 | |
|
|
1635c81efd | |
|
|
68f7fd9961 | |
|
|
fcdaa0a743 | |
|
|
cf50ea1eca | |
|
|
1905297463 | |
|
|
735198da58 | |
|
|
b604114074 | |
|
|
9e0274a552 | |
|
|
0753f3b855 | |
|
|
5b5962d868 | |
|
|
0675feaf6b | |
|
|
e1d9aaa3cd | |
|
|
019fc1bef7 | |
|
|
fe905a310f | |
|
|
35a9155688 | |
|
|
7de89c5f72 | |
|
|
0511bb8de6 | |
|
|
a9633d030d | |
|
|
e2c7c43f3a | |
|
|
abf21c6560 | |
|
|
a9549ca708 | |
|
|
f69f1f4058 | |
|
|
fe0392a514 | |
|
|
4f187d2f88 | |
|
|
bc28e21cec | |
|
|
d83d25d538 | |
|
|
516727006b | |
|
|
15a721ddc3 | |
|
|
62985d3573 | |
|
|
7747bb4f1d | |
|
|
1566a11c50 | |
|
|
01e0658403 | |
|
|
4c2e61e80d | |
|
|
cf2916d758 | |
|
|
367c91fc06 | |
|
|
60fb6dfb4e | |
|
|
dc7db12af0 | |
|
|
2c9d3acbe9 | |
|
|
527357081b | |
|
|
759578bc75 | |
|
|
53728ddd40 | |
|
|
669702b0c9 | |
|
|
9266e989fa | |
|
|
9b78ad0301 | |
|
|
9c39af1525 | |
|
|
2eddade7d5 | |
|
|
5241de2d4a | |
|
|
ba0571ffb8 | |
|
|
28d41782a7 | |
|
|
092482fe02 | |
|
|
c7dffc852d | |
|
|
80ed6b0d64 | |
|
|
7e5c08654b | |
|
|
d7fe92f930 | |
|
|
256942fb22 | |
|
|
d01f202cfa | |
|
|
afbe799688 | |
|
|
b2ae794dd7 | |
|
|
b6ace1c58d | |
|
|
ef183f04cd | |
|
|
97df2e7fd1 | |
|
|
3ce85f5126 | |
|
|
07bb08198c | |
|
|
0f4991d813 | |
|
|
6ad14e6c29 | |
|
|
f74fed702c | |
|
|
432ec45fb8 | |
|
|
9371145001 | |
|
|
8c92342a7f | |
|
|
930be27403 | |
|
|
f0cc12c0b1 | |
|
|
4c47526729 | |
|
|
6d996e1a1e | |
|
|
46fe2cbddc | |
|
|
81e2c85dab | |
|
|
15bcd284b9 | |
|
|
c84a1c15df | |
|
|
91cdf35900 |
|
|
@ -37,7 +37,6 @@ framework_utils_cc_defaults {
|
|||
|
||||
cflags: [
|
||||
"-fvisibility=hidden",
|
||||
"-DCONFIG_NET_RPMSG",
|
||||
],
|
||||
|
||||
soong_config_variables: {
|
||||
|
|
|
|||
9
Kconfig
9
Kconfig
|
|
@ -102,13 +102,12 @@ if !KVDB_DIRECT
|
|||
|
||||
config KVDB_SERVER_CPUNAME
|
||||
string "which cpu kvdb server runs on"
|
||||
depends on NET_RPMSG
|
||||
depends on !KVDB_SERVER
|
||||
default "ap"
|
||||
|
||||
config KVDB_TIMEOUT_INTERVAL
|
||||
int "transaction timeout interval(usec)"
|
||||
default 5000000
|
||||
depends on NET_SOCKOPTS
|
||||
int "transaction timeout interval(sec)"
|
||||
default 0
|
||||
|
||||
endif
|
||||
|
||||
|
|
@ -120,7 +119,7 @@ config KVDB_COMMIT_INTERVAL
|
|||
config KVDB_BACKLOG_CONNS
|
||||
int "backlog connections"
|
||||
depends on KVDB_SERVER
|
||||
default 256
|
||||
default 32
|
||||
|
||||
if KVDB_DIRECT || KVDB_SERVER
|
||||
|
||||
|
|
|
|||
2053
gdbus/client.c
2053
gdbus/client.c
File diff suppressed because it is too large
Load Diff
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Xiaomi Technologies Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of the Xiaomi project.
|
||||
*
|
||||
* This source code is licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <uv_ext.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
|
||||
#include "syslog.h"
|
||||
|
||||
#include "gdbus.h"
|
||||
|
||||
#define error(fmt, ...) \
|
||||
do { \
|
||||
syslog(LOG_ERR, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define warning(fmt, ...) \
|
||||
do { \
|
||||
syslog(LOG_WARNING, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define info(fmt, ...) \
|
||||
do { \
|
||||
syslog(LOG_INFO, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define debug(fmt, ...) \
|
||||
do { \
|
||||
syslog(LOG_DEBUG, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
struct GDBusClient {
|
||||
int ref_count;
|
||||
DBusConnection* dbus_conn;
|
||||
char* service_name;
|
||||
char* base_path;
|
||||
char* root_path;
|
||||
guint watch;
|
||||
guint added_watch;
|
||||
guint removed_watch;
|
||||
struct ptr_array* match_rules;
|
||||
DBusPendingCall* pending_call;
|
||||
DBusPendingCall* get_objects_call;
|
||||
GDBusWatchFunction connect_func;
|
||||
void* connect_data;
|
||||
GDBusWatchFunction disconn_func;
|
||||
gboolean connected;
|
||||
void* disconn_data;
|
||||
GDBusMessageFunction signal_func;
|
||||
void* signal_data;
|
||||
GDBusProxyFunction proxy_added;
|
||||
GDBusProxyFunction proxy_removed;
|
||||
GDBusProxyPropertyFilterFunction proxy_property_filter;
|
||||
GDBusProxyFilterFunction proxy_filter;
|
||||
GDBusClientFunction ready;
|
||||
void* ready_data;
|
||||
gboolean ready_called;
|
||||
GDBusPropertyFunction property_changed;
|
||||
void* user_data;
|
||||
DBusList* proxy_list;
|
||||
gboolean standard;
|
||||
gboolean getting_object_call;
|
||||
uv_async_queue_t async_queue;
|
||||
uv_thread_t main_thread;
|
||||
GDBusWatch *watcher;
|
||||
};
|
||||
|
||||
struct GDBusProxy {
|
||||
int ref_count;
|
||||
GDBusClient* client;
|
||||
char* obj_path;
|
||||
char* interface;
|
||||
DBusHashTable* prop_list;
|
||||
guint watch;
|
||||
guint watch_non_standard;
|
||||
GDBusPropertyFunction prop_func;
|
||||
void* prop_data;
|
||||
GDBusProxyFunction removed_func;
|
||||
void* removed_data;
|
||||
DBusPendingCall* get_all_call;
|
||||
gboolean pending;
|
||||
gboolean filter_first;
|
||||
gboolean getting_all_prop;
|
||||
};
|
||||
|
||||
GDBusWatch* new_dbus_watch(DBusConnection* connection);
|
||||
void free_dbus_watch(GDBusWatch* watcher);
|
||||
void dbus_watch_set_connection_state(GDBusWatch* watcher, gboolean closed);
|
||||
|
||||
int dbus_polkit_check_authorization(DBusConnection* conn,
|
||||
const char* action, gboolean allow_interaction,
|
||||
void (*callback)(dbus_bool_t, void*),
|
||||
void* user_data, int timeout_ms);
|
||||
964
gdbus/gdbus.h
964
gdbus/gdbus.h
|
|
@ -1,964 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Xiaomi Technologies Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of the Xiaomi project.
|
||||
*
|
||||
* This source code is licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __GDBUS_H
|
||||
#define __GDBUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
typedef void* gpointer;
|
||||
typedef int gboolean;
|
||||
typedef unsigned int guint;
|
||||
typedef uint32_t guint32;
|
||||
|
||||
#define g_dbus_setup_bus dbus_setup_bus
|
||||
#define g_dbus_setup_private dbus_setup_private
|
||||
#define g_dbus_request_name dbus_request_name
|
||||
#define g_dbus_set_flags dbus_set_flags
|
||||
#define g_dbus_get_flags dbus_get_flags
|
||||
#define g_dbus_register_interface dbus_register_interface
|
||||
#define g_dbus_unregister_interface dbus_unregister_interface
|
||||
#define g_dbus_register_security dbus_register_security
|
||||
#define g_dbus_unregister_security dbus_unregister_security
|
||||
#define g_dbus_pending_success dbus_pending_success
|
||||
#define g_dbus_pending_error dbus_pending_error
|
||||
#define g_dbus_pending_error_valist dbus_pending_error_valist
|
||||
#define g_dbus_create_error dbus_create_error
|
||||
#define g_dbus_create_error_valist dbus_create_error_valist
|
||||
#define g_dbus_create_reply dbus_create_reply
|
||||
#define g_dbus_create_reply_valist dbus_create_reply_valist
|
||||
#define g_dbus_send_message dbus_send_message
|
||||
#define g_dbus_send_message_with_reply dbus_send_message_with_reply
|
||||
#define g_dbus_send_error dbus_send_error
|
||||
#define g_dbus_send_error_valist dbus_send_error_valist
|
||||
#define g_dbus_send_reply dbus_send_reply
|
||||
#define g_dbus_send_reply_valist dbus_send_reply_valist
|
||||
#define g_dbus_emit_signal dbus_emit_signal
|
||||
#define g_dbus_emit_signal_valist dbus_emit_signal_valist
|
||||
#define g_dbus_pending_property_success dbus_pending_property_success
|
||||
#define g_dbus_pending_property_error_valist dbus_pending_property_error_valist
|
||||
#define g_dbus_pending_property_error dbus_pending_property_error
|
||||
#define g_dbus_emit_property_changed dbus_emit_property_changed
|
||||
#define g_dbus_emit_property_changed_full dbus_emit_property_changed_full
|
||||
#define g_dbus_get_properties dbus_get_properties
|
||||
#define g_dbus_attach_object_manager dbus_attach_object_manager
|
||||
#define g_dbus_detach_object_manager dbus_detach_object_manager
|
||||
#define g_dbus_proxy_new dbus_proxy_new
|
||||
#define g_dbus_proxy_ref dbus_proxy_ref
|
||||
#define g_dbus_proxy_unref dbus_proxy_unref
|
||||
#define g_dbus_proxy_get_path dbus_proxy_get_path
|
||||
#define g_dbus_proxy_get_interface dbus_proxy_get_interface
|
||||
#define g_dbus_proxy_get_property dbus_proxy_get_property
|
||||
#define g_dbus_proxy_get_property_basic dbus_proxy_get_property_basic
|
||||
#define g_dbus_proxy_get_property_iter_cb dbus_proxy_get_property_iter_cb
|
||||
#define g_dbus_proxy_lookup dbus_proxy_lookup
|
||||
#define g_dbus_proxy_path_lookup dbus_proxy_path_lookup
|
||||
#define g_dbus_proxy_refresh_property dbus_proxy_refresh_property
|
||||
#define g_dbus_proxy_set_property_basic dbus_proxy_set_property_basic
|
||||
#define g_dbus_proxy_set_property_array dbus_proxy_set_property_array
|
||||
#define g_dbus_dict_append_entry dbus_dict_append_entry
|
||||
#define g_dbus_dict_append_basic_array dbus_dict_append_basic_array
|
||||
#define g_dbus_dict_append_array dbus_dict_append_array
|
||||
#define g_dbus_proxy_method_call dbus_proxy_method_call
|
||||
#define g_dbus_proxy_set_property_watch dbus_proxy_set_property_watch
|
||||
#define g_dbus_proxy_remove_property_watch dbus_proxy_remove_property_watch
|
||||
#define g_dbus_proxy_set_removed_watch dbus_proxy_set_removed_watch
|
||||
#define g_dbus_client_new dbus_client_new
|
||||
#define g_dbus_client_new_full dbus_client_new_full
|
||||
#define g_dbus_client_ref dbus_client_ref
|
||||
#define g_dbus_client_unref dbus_client_unref
|
||||
#define g_dbus_client_set_connect_watch dbus_client_set_connect_watch
|
||||
#define g_dbus_client_set_disconnect_watch dbus_client_set_disconnect_watch
|
||||
#define g_dbus_client_set_signal_watch dbus_client_set_signal_watch
|
||||
#define g_dbus_client_set_ready_watch dbus_client_set_ready_watch
|
||||
#define g_dbus_client_set_proxy_handlers dbus_client_set_proxy_handlers
|
||||
#define g_dbus_client_set_proxy_filter dbus_client_set_proxy_filter
|
||||
|
||||
typedef struct GDBusArgInfo GDBusArgInfo;
|
||||
typedef struct GDBusMethodTable GDBusMethodTable;
|
||||
typedef struct GDBusSignalTable GDBusSignalTable;
|
||||
typedef struct GDBusPropertyTable GDBusPropertyTable;
|
||||
typedef struct GDBusSecurityTable GDBusSecurityTable;
|
||||
|
||||
typedef void (*GDBusWatchFunction)(DBusConnection* connection,
|
||||
void* user_data);
|
||||
|
||||
typedef void (*GDBusMessageFunction)(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data);
|
||||
|
||||
typedef gboolean (*GDBusSignalFunction)(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data);
|
||||
|
||||
typedef void (*GDBusPropIterFunction)(DBusMessageIter* iter, void* value);
|
||||
|
||||
/**
|
||||
* @brief Set and connect to the specified DBus bus type
|
||||
*
|
||||
* @param type the type of DBus bus, which can be DBUS_BUS_SESSION or DBUS_BUS_SYSTEM
|
||||
* @param name The name of the DBus bus to connect to
|
||||
* @param error A DBusError structure used to store error information
|
||||
*
|
||||
* @return If successful, returns a pointer to DBusConnection; if failed, returns NULL
|
||||
*/
|
||||
DBusConnection* dbus_setup_bus(DBusBusType type, const char* name, DBusError* error);
|
||||
|
||||
/**
|
||||
* @brief Set up a private DBus connection
|
||||
*
|
||||
* This function is used to set up a private DBus connection. It accepts a DBusBusType
|
||||
* parameter that specifies the type of connection (session or system), a string parameter
|
||||
* that is the name of the DBus you want to connect to, and a DBusError pointer to store
|
||||
* any error information that may occur.
|
||||
* If the function succeeds, it returns a pointer to a DBusConnection, otherwise it returns NULL.
|
||||
*
|
||||
* @param type The type of DBus connection, which can be DBUS_BUS_SESSION or DBUS_BUS_SYSTEM
|
||||
* @param name The name of the DBus you want to connect to
|
||||
* @param error A DBusError structure used to store error information
|
||||
* @return Returns a DBusConnection pointer on success, or NULL on failure
|
||||
*/
|
||||
DBusConnection* dbus_setup_private(DBusBusType type, const char* name, DBusError* error);
|
||||
|
||||
/**
|
||||
* @brief Requests a specific D-Bus name on the specified DBus connection.
|
||||
*
|
||||
* @param connection Pointer to a DBusConnection object representing the connection for
|
||||
* which the name is to be requested.
|
||||
* @param name String of the D-Bus name to be requested.
|
||||
* @param error Pointer to a DBusError object for storing possible errors that may occur
|
||||
* during the name request.
|
||||
*
|
||||
* @return Returns a gboolean value of TRUE if the request succeeds or a gboolean value
|
||||
* of FALSE if the request fails.
|
||||
*/
|
||||
gboolean dbus_request_name(DBusConnection* connection, const char* name, DBusError* error);
|
||||
|
||||
typedef void (*GDBusDestroyFunction)(void* user_data);
|
||||
|
||||
typedef DBusMessage* (*GDBusMethodFunction)(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data);
|
||||
|
||||
typedef gboolean (*GDBusPropertyGetter)(const GDBusPropertyTable* property,
|
||||
DBusMessageIter* iter, void* data);
|
||||
|
||||
typedef guint32 GDBusPendingPropertySet;
|
||||
|
||||
typedef void (*GDBusPropertySetter)(const GDBusPropertyTable* property,
|
||||
DBusMessageIter* value, GDBusPendingPropertySet id,
|
||||
void* data);
|
||||
|
||||
typedef gboolean (*GDBusPropertyExists)(const GDBusPropertyTable* property,
|
||||
void* data);
|
||||
|
||||
typedef guint32 GDBusPendingReply;
|
||||
|
||||
typedef void (*GDBusSecurityFunction)(DBusConnection* connection,
|
||||
const char* action,
|
||||
gboolean interaction,
|
||||
GDBusPendingReply pending);
|
||||
|
||||
enum GDBusFlags {
|
||||
G_DBUS_FLAG_ENABLE_EXPERIMENTAL = (1 << 0),
|
||||
};
|
||||
|
||||
enum GDBusMethodFlags {
|
||||
G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
|
||||
G_DBUS_METHOD_FLAG_NOREPLY = (1 << 1),
|
||||
G_DBUS_METHOD_FLAG_ASYNC = (1 << 2),
|
||||
G_DBUS_METHOD_FLAG_EXPERIMENTAL = (1 << 3),
|
||||
};
|
||||
|
||||
enum GDBusSignalFlags {
|
||||
G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0),
|
||||
G_DBUS_SIGNAL_FLAG_EXPERIMENTAL = (1 << 1),
|
||||
};
|
||||
|
||||
enum GDBusPropertyFlags {
|
||||
G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0),
|
||||
G_DBUS_PROPERTY_FLAG_EXPERIMENTAL = (1 << 1),
|
||||
};
|
||||
|
||||
enum GDBusSecurityFlags {
|
||||
G_DBUS_SECURITY_FLAG_DEPRECATED = (1 << 0),
|
||||
G_DBUS_SECURITY_FLAG_BUILTIN = (1 << 1),
|
||||
G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION = (1 << 2),
|
||||
};
|
||||
|
||||
enum GDbusPropertyChangedFlags {
|
||||
G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH = (1 << 0),
|
||||
};
|
||||
|
||||
typedef enum GDBusMethodFlags GDBusMethodFlags;
|
||||
typedef enum GDBusSignalFlags GDBusSignalFlags;
|
||||
typedef enum GDBusPropertyFlags GDBusPropertyFlags;
|
||||
typedef enum GDBusSecurityFlags GDBusSecurityFlags;
|
||||
typedef enum GDbusPropertyChangedFlags GDbusPropertyChangedFlags;
|
||||
|
||||
struct GDBusArgInfo {
|
||||
const char* name;
|
||||
const char* signature;
|
||||
};
|
||||
|
||||
struct GDBusMethodTable {
|
||||
const char* name;
|
||||
GDBusMethodFunction function;
|
||||
GDBusMethodFlags flags;
|
||||
unsigned int privilege;
|
||||
const GDBusArgInfo* in_args;
|
||||
const GDBusArgInfo* out_args;
|
||||
};
|
||||
|
||||
struct GDBusSignalTable {
|
||||
const char* name;
|
||||
GDBusSignalFlags flags;
|
||||
const GDBusArgInfo* args;
|
||||
};
|
||||
|
||||
struct GDBusPropertyTable {
|
||||
const char* name;
|
||||
const char* type;
|
||||
GDBusPropertyGetter get;
|
||||
GDBusPropertySetter set;
|
||||
GDBusPropertyExists exists;
|
||||
GDBusPropertyFlags flags;
|
||||
};
|
||||
|
||||
struct GDBusSecurityTable {
|
||||
unsigned int privilege;
|
||||
const char* action;
|
||||
GDBusSecurityFlags flags;
|
||||
GDBusSecurityFunction function;
|
||||
};
|
||||
|
||||
#define GDBUS_ARGS(args...) \
|
||||
(const GDBusArgInfo[]) \
|
||||
{ \
|
||||
args, { } \
|
||||
}
|
||||
|
||||
#define GDBUS_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function
|
||||
|
||||
#define GDBUS_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_ASYNC
|
||||
|
||||
#define GDBUS_DEPRECATED_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_DEPRECATED
|
||||
|
||||
#define GDBUS_DEPRECATED_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_DEPRECATED
|
||||
|
||||
#define GDBUS_EXPERIMENTAL_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_EXPERIMENTAL
|
||||
|
||||
#define GDBUS_EXPERIMENTAL_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_EXPERIMENTAL
|
||||
|
||||
#define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \
|
||||
.name = _name, \
|
||||
.in_args = _in_args, \
|
||||
.out_args = _out_args, \
|
||||
.function = _function, \
|
||||
.flags = G_DBUS_METHOD_FLAG_NOREPLY
|
||||
|
||||
#define GDBUS_SIGNAL(_name, _args) \
|
||||
.name = _name, \
|
||||
.args = _args
|
||||
|
||||
#define GDBUS_DEPRECATED_SIGNAL(_name, _args) \
|
||||
.name = _name, \
|
||||
.args = _args, \
|
||||
.flags = G_DBUS_SIGNAL_FLAG_DEPRECATED
|
||||
|
||||
#define GDBUS_EXPERIMENTAL_SIGNAL(_name, _args) \
|
||||
.name = _name, \
|
||||
.args = _args, \
|
||||
.flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL
|
||||
|
||||
void dbus_set_flags(int flags);
|
||||
int dbus_get_flags(void);
|
||||
|
||||
/**
|
||||
* @brief Register an interface on the specified DBus connection
|
||||
*
|
||||
* This function is used to register an interface on the specified DBus connection.
|
||||
* It requires the following parameters:
|
||||
* - connection: DBus connection object
|
||||
* - path: path of DBus interface
|
||||
* - name: name of DBus interface
|
||||
* - methods: a GDBusMethodTable object containing methods of interface
|
||||
* - signals: a GDBusSignalTable object containing signals of interface
|
||||
* - properties: a GDBusPropertyTable object containing properties of interface
|
||||
* - user_data: user data, which can be passed to callback function
|
||||
* - destroy: a GDBusDestroyFunction, which is called when the interface is deregistered
|
||||
* to clean up user data
|
||||
*
|
||||
* @param connection DBus connection object
|
||||
* @param path path of DBus interface
|
||||
* @param name name of DBus interface
|
||||
* @param methods GDBusMethodTable object containing interface methods
|
||||
* @param signals GDBusSignalTable object containing interface signals
|
||||
* @param properties GDBusPropertyTable object containing interface properties
|
||||
* @param user_data user data
|
||||
* @param destroy GDBusDestroyFunction for cleaning up user data
|
||||
* @return gboolean Returns TRUE if registration is successful, and FALSE if fails
|
||||
*/
|
||||
gboolean dbus_register_interface(DBusConnection* connection,
|
||||
const char* path, const char* name,
|
||||
const GDBusMethodTable* methods,
|
||||
const GDBusSignalTable* signals,
|
||||
const GDBusPropertyTable* properties,
|
||||
void* user_data,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* @brief Unregister the specified interface from the specified DBus connection
|
||||
*
|
||||
* @param connection Pointer to DBusConnection, indicating the DBus connection of the
|
||||
* interface to be unregistered
|
||||
* @param path Path of the interface
|
||||
* @param name Name of the interface
|
||||
* @return If the interface is successfully unregistered, return gboolean TRUE, otherwise
|
||||
* return FALSE
|
||||
*/
|
||||
gboolean dbus_unregister_interface(DBusConnection* connection,
|
||||
const char* path, const char* name);
|
||||
|
||||
gboolean dbus_register_security(const GDBusSecurityTable* security);
|
||||
gboolean dbus_unregister_security(const GDBusSecurityTable* security);
|
||||
|
||||
void dbus_pending_success(DBusConnection* connection,
|
||||
GDBusPendingReply pending);
|
||||
void dbus_pending_error(DBusConnection* connection,
|
||||
GDBusPendingReply pending,
|
||||
const char* name, const char* format, ...)
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
void dbus_pending_error_valist(DBusConnection* connection,
|
||||
GDBusPendingReply pending, const char* name,
|
||||
const char* format, va_list args);
|
||||
|
||||
DBusMessage* dbus_create_error(DBusMessage* message, const char* name,
|
||||
const char* format, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
DBusMessage* dbus_create_error_valist(DBusMessage* message, const char* name,
|
||||
const char* format, va_list args);
|
||||
DBusMessage* dbus_create_reply(DBusMessage* message, int type, ...);
|
||||
DBusMessage* dbus_create_reply_valist(DBusMessage* message,
|
||||
int type, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Send a message to the specified DBus connection
|
||||
*
|
||||
* @param connection Pointer to the DBusConnection object, indicating the DBus connection
|
||||
* to send the message
|
||||
* @param message Pointer to the DBusMessage object, indicating the message to send
|
||||
*
|
||||
* @return If the sending is successful, return the gboolean type with a value of TRUE;
|
||||
* if the sending fails, return the gboolean type with a value of FALSE
|
||||
*/
|
||||
gboolean dbus_send_message(DBusConnection* connection, DBusMessage* message);
|
||||
|
||||
/**
|
||||
* @brief Send a message to the specified DBus connection and wait for a reply,
|
||||
* non-blocking call
|
||||
*
|
||||
* @param connection Pointer to the DBusConnection object, indicating the DBus connection
|
||||
* @param message Pointer to the DBusMessage object, indicating the message to be sent
|
||||
* @param call Pointer to the pointer to the DBusPendingCall object, used to store the
|
||||
* handle of the asynchronous call
|
||||
* @param timeout Timeout for waiting for a reply after sending a message, in milliseconds
|
||||
*
|
||||
* @return If the message is successfully sent and the DBusPendingCall object instance is
|
||||
* replied, the return value of the gboolean type is TRUE; otherwise, it returns FALSE
|
||||
*/
|
||||
gboolean dbus_send_message_with_reply(DBusConnection* connection, DBusMessage* message,
|
||||
DBusPendingCall** call, int timeout);
|
||||
|
||||
gboolean dbus_send_error(DBusConnection* connection, DBusMessage* message,
|
||||
const char* name, const char* format, ...)
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
gboolean dbus_send_error_valist(DBusConnection* connection,
|
||||
DBusMessage* message, const char* name,
|
||||
const char* format, va_list args);
|
||||
gboolean dbus_send_reply(DBusConnection* connection,
|
||||
DBusMessage* message, int type, ...);
|
||||
gboolean dbus_send_reply_valist(DBusConnection* connection,
|
||||
DBusMessage* message, int type, va_list args);
|
||||
|
||||
gboolean dbus_emit_signal(DBusConnection* connection,
|
||||
const char* path, const char* interface,
|
||||
const char* name, int type, ...);
|
||||
gboolean dbus_emit_signal_valist(DBusConnection* connection,
|
||||
const char* path, const char* interface,
|
||||
const char* name, int type, va_list args);
|
||||
|
||||
typedef struct GDBusWatch GDBusWatch;
|
||||
|
||||
/**
|
||||
* Adds a service watch to monitor the specified D-Bus service name
|
||||
*
|
||||
* @param watcher The GDBusWatch instance to add the watch to
|
||||
* @param name The D-Bus service name to watch (e.g. "org.freedesktop.DBus")
|
||||
* @param connect Callback function when service connects
|
||||
* @param disconnect Callback function when service disconnects
|
||||
* @param user_data User data passed to callbacks
|
||||
* @param destroy Destroy notification callback for user_data
|
||||
* @return Watch ID that can be used to remove the watch
|
||||
*/
|
||||
guint dbus_add_service_watch(GDBusWatch* watcher, const char* name,
|
||||
GDBusWatchFunction connect, GDBusWatchFunction disconnect,
|
||||
void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* Adds a disconnect watch for the specified D-Bus name
|
||||
*
|
||||
* @param watcher The GDBusWatch instance to add the watch to
|
||||
* @param name The D-Bus name to monitor for disconnection
|
||||
* @param function Callback function when name disconnects
|
||||
* @param user_data User data passed to callback
|
||||
* @param destroy Destroy notification callback for user_data
|
||||
* @return Watch ID that can be used to remove the watch
|
||||
*/
|
||||
guint dbus_add_service_disconnect_watch(GDBusWatch* watcher, const char* name,
|
||||
GDBusWatchFunction function, void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* @brief Add a signal monitor to the DBus connection
|
||||
*
|
||||
* @param connection: Pointer to DBusConnection, indicating the DBus connection to which
|
||||
* the signal monitor is to be added
|
||||
* @param sender: The name of the DBus client that sends the signal. If it is NULL, the
|
||||
* signals of all clients are monitored
|
||||
* @param path: The path of the signal. If it is NULL, the signals of all paths are
|
||||
* monitored
|
||||
* @param interface: The interface of the signal. If it is NULL, the signals of all
|
||||
* interfaces are monitored
|
||||
* @param member: The member of the signal, that is, the specific name of the signal.
|
||||
* If it is NULL, the signals of all members are monitored
|
||||
* @param function: The function called when the signal is received receives the
|
||||
* following parameters:
|
||||
* - DBusConnection*: DBus connection
|
||||
* - const char*: The sender of the signal
|
||||
* - const char*: The path of the signal
|
||||
* - const char*: The interface of the signal
|
||||
* - const char*: The member of the signal
|
||||
* - void*: User data
|
||||
* @param user_data: User data, which will be passed to the function when calling the
|
||||
* function
|
||||
* @param destroy: The function called when the signal monitor is removed to destroy
|
||||
* user_data. If it is NULL, no action is performed.
|
||||
* @return: Returns an unsigned integer representing the ID of the newly created signal
|
||||
* monitor.
|
||||
*/
|
||||
guint dbus_add_signal_watch(GDBusWatch* watcher,
|
||||
const char* sender, const char* path,
|
||||
const char* interface, const char* member,
|
||||
GDBusSignalFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
guint dbus_add_properties_watch(GDBusWatch* watcher,
|
||||
const char* sender, const char* path,
|
||||
const char* interface,
|
||||
GDBusSignalFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* @brief Remove a specific watch from the specified DBus connection
|
||||
*
|
||||
* @param connection Pointer to DBusConnection, indicating the connection from which the
|
||||
* watch is to be removed
|
||||
* @param tag Indicates the unique identifier of the watch to be removed
|
||||
*
|
||||
* @return gboolean The function returns TRUE if executed successfully, otherwise returns
|
||||
* FALSE
|
||||
*/
|
||||
gboolean dbus_remove_watch(GDBusWatch* watcher, guint tag);
|
||||
|
||||
void dbus_remove_all_watches(GDBusWatch* watcher);
|
||||
|
||||
void dbus_pending_property_success(GDBusPendingPropertySet id);
|
||||
void dbus_pending_property_error_valist(GDBusPendingReply id,
|
||||
const char* name, const char* format, va_list args);
|
||||
void dbus_pending_property_error(GDBusPendingReply id, const char* name,
|
||||
const char* format, ...);
|
||||
|
||||
/*
|
||||
* Note that when multiple properties for a given object path are changed
|
||||
* in the same mainloop iteration, they will be grouped with the last
|
||||
* property changed. If this behaviour is undesired, use
|
||||
* dbus_emit_property_changed_full() with the
|
||||
* G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH flag, causing the signal to ignore
|
||||
* any grouping.
|
||||
*/
|
||||
void dbus_emit_property_changed(DBusConnection* connection,
|
||||
const char* path, const char* interface,
|
||||
const char* name);
|
||||
void dbus_emit_property_changed_full(DBusConnection* connection,
|
||||
const char* path, const char* interface,
|
||||
const char* name,
|
||||
GDbusPropertyChangedFlags flags);
|
||||
gboolean dbus_get_properties(DBusConnection* connection, const char* path,
|
||||
const char* interface, DBusMessageIter* iter);
|
||||
|
||||
gboolean dbus_attach_object_manager(DBusConnection* connection);
|
||||
gboolean dbus_detach_object_manager(DBusConnection* connection);
|
||||
|
||||
typedef struct GDBusClient GDBusClient;
|
||||
typedef struct GDBusProxy GDBusProxy;
|
||||
|
||||
/**
|
||||
* @brief Create a new D-Bus proxy object
|
||||
*
|
||||
* This function is used to create a new D-Bus proxy object.
|
||||
*
|
||||
* @param client Pointer to the GDBusClient object, which is an instance of the
|
||||
* D-Bus client.
|
||||
* @param path The path of the D-Bus proxy.
|
||||
* @param interface The name of the interface to be implemented by the D-Bus proxy.
|
||||
*
|
||||
* @return Returns a pointer to the GDBusProxy object if it was created successfully,
|
||||
* otherwise returns NULL.
|
||||
*/
|
||||
GDBusProxy* dbus_proxy_new(GDBusClient* client, const char* path,
|
||||
const char* interface);
|
||||
|
||||
/**
|
||||
* @brief Increase the reference count of a D-Bus proxy
|
||||
*
|
||||
* This function increases the reference count of a given D-Bus proxy.
|
||||
*
|
||||
* @param proxy Pointer to the D-Bus proxy whose reference count is to be increased.
|
||||
* @return Returns the pointer to the D-Bus proxy after the reference count is increased.
|
||||
*/
|
||||
GDBusProxy* dbus_proxy_ref(GDBusProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief Decrement the reference count of a D-Bus proxy
|
||||
*
|
||||
* This function decrements the reference count of a given D-Bus proxy. If the reference
|
||||
* count reaches 0, the proxy will be released.
|
||||
*
|
||||
* @param proxy Pointer to the D-Bus proxy whose reference count is to be decremented.
|
||||
*/
|
||||
void dbus_proxy_unref(GDBusProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief Get the path of the D-Bus proxy
|
||||
*
|
||||
* @param proxy Pointer to GDBusProxy
|
||||
* @return Return the path of the proxy
|
||||
*/
|
||||
const char* dbus_proxy_get_path(const GDBusProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief Get the interface of the D-Bus proxy
|
||||
*
|
||||
* @param proxy Pointer to GDBusProxy
|
||||
* @return Return the interface of the proxy
|
||||
*/
|
||||
const char* dbus_proxy_get_interface(GDBusProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief Gets a property value from a D-Bus proxy object, should run
|
||||
* in uv default loop.
|
||||
*
|
||||
* @param proxy The D-Bus proxy object to query
|
||||
* @param name The name of the property to get
|
||||
* @param iter Pointer to a DBusMessageIter to store the property value
|
||||
* @return gboolean TRUE if successful, FALSE otherwise
|
||||
*
|
||||
* This function synchronously gets a property value from a D-Bus proxy object
|
||||
* and stores it in the provided DBusMessageIter. The caller is responsible
|
||||
* for properly handling the DBusMessageIter contents.
|
||||
*/
|
||||
gboolean dbus_proxy_get_property(GDBusProxy* proxy, const char* name,
|
||||
DBusMessageIter* iter);
|
||||
|
||||
/**
|
||||
* @brief Gets a basic property value from a D-Bus proxy object (thread-safe)
|
||||
*
|
||||
* @param proxy The D-Bus proxy object to query
|
||||
* @param name The name of the property to get
|
||||
* @param value Pointer to store the property value (must match property type)
|
||||
* @return gboolean TRUE if successful, FALSE otherwise
|
||||
*
|
||||
* This function synchronously gets a basic type property value from a D-Bus
|
||||
* proxy object in a thread-safe manner. For complex struct properties,
|
||||
* please use dbus_proxy_get_property_iter_cb instead. The value parameter
|
||||
* must point to storage of the correct type for the property being retrieved.
|
||||
*/
|
||||
gboolean dbus_proxy_get_property_basic(GDBusProxy* proxy, const char* name,
|
||||
void* value);
|
||||
|
||||
/**
|
||||
* Asynchronously gets a D-Bus proxy property with thread safety
|
||||
*
|
||||
* @param proxy The D-Bus proxy object to query
|
||||
* @param name Name of the property to retrieve
|
||||
* @param value Pointer to store the property value
|
||||
* @param iter_cb Callback function to handle property iteration
|
||||
* @return TRUE if property was successfully retrieved, FALSE on error
|
||||
*
|
||||
* @note This function handles thread synchronization automatically.
|
||||
* It can be called from any thread but will block if not in default loop.
|
||||
*/
|
||||
gboolean dbus_proxy_get_property_iter_cb(GDBusProxy* proxy, const char* name,
|
||||
void* value, GDBusPropIterFunction iter_cb);
|
||||
|
||||
GDBusProxy* dbus_proxy_lookup(void* list, int* index, const char* path,
|
||||
const char* interface);
|
||||
char* dbus_proxy_path_lookup(void* list, int* index, const char* path);
|
||||
|
||||
gboolean dbus_proxy_refresh_property(GDBusProxy* proxy, const char* name);
|
||||
|
||||
typedef void (*GDBusResultFunction)(const DBusError* error, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief This function is used to set the properties of a D-Bus proxy.
|
||||
*
|
||||
* @param proxy Pointer to GDBusProxy, indicating the proxy to set the properties.
|
||||
* @param name The name of the property, which should be a string type.
|
||||
* @param type The type of the property, which should be an integer, indicating the data
|
||||
* type of the property.
|
||||
* @param value Pointer to the value of the property, which should be a void type,
|
||||
* indicating the value of the property.
|
||||
* @param function Pointer to GDBusResultFunction, indicating the function to be executed
|
||||
* after setting the property.
|
||||
* @param user_data Pointer to user data, which will be passed when executing
|
||||
* the @param function function.
|
||||
* @param destroy Pointer to GDBusDestroyFunction, indicating how to destroy the data
|
||||
* pointed to by value when the set property is no longer needed.
|
||||
*
|
||||
* @return Returns a true value of type gboolean if the property is successfully set;
|
||||
* otherwise, returns a false value.
|
||||
*/
|
||||
gboolean dbus_proxy_set_property_basic(GDBusProxy* proxy,
|
||||
const char* name, int type, const void* value,
|
||||
GDBusResultFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
gboolean dbus_proxy_set_property_array(GDBusProxy* proxy,
|
||||
const char* name, int type, const void* value,
|
||||
size_t size, GDBusResultFunction function,
|
||||
void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
void dbus_dict_append_entry(DBusMessageIter* dict,
|
||||
const char* key, int type, void* val);
|
||||
void dbus_dict_append_basic_array(DBusMessageIter* dict, int key_type,
|
||||
const void* key, int type, void* val,
|
||||
int n_elements);
|
||||
void dbus_dict_append_array(DBusMessageIter* dict,
|
||||
const char* key, int type, void* val,
|
||||
int n_elements);
|
||||
|
||||
typedef void (*GDBusSetupFunction)(DBusMessageIter* iter, void* user_data);
|
||||
typedef void (*GDBusReturnFunction)(DBusMessage* message, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Calls the specified @method method on the given D-Bus proxy
|
||||
*
|
||||
* @param proxy Pointer to GDBusProxy, indicating the D-Bus proxy to be called
|
||||
* @param method The name of the method to be called
|
||||
* @param setup A GDBusSetupFunction, used to set the parameters of the method call
|
||||
* @param function A GDBusReturnFunction, called after the method call succeeds,
|
||||
* returns the return value of the method
|
||||
* @param user_data User data, passed to GDBusReturnFunction
|
||||
* @param destroy A GDBusDestroyFunction, called after the method call is completed,
|
||||
* used to clean up resources
|
||||
*
|
||||
* @return Returns gboolean if the method call succeeds, otherwise returns gboolean
|
||||
*/
|
||||
gboolean dbus_proxy_method_call(GDBusProxy* proxy, const char* method,
|
||||
GDBusSetupFunction setup,
|
||||
GDBusReturnFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
typedef void (*GDBusClientFunction)(GDBusClient* client, void* user_data);
|
||||
typedef void (*GDBusProxyFunction)(GDBusProxy* proxy, void* user_data);
|
||||
typedef gboolean (*GDBusProxyPropertyFilterFunction)(GDBusProxy* proxy, void* user_data);
|
||||
typedef void (*GDBusPropertyFunction)(GDBusProxy* proxy, const char* name,
|
||||
DBusMessageIter* iter, void* user_data);
|
||||
typedef gboolean (*GDBusProxyFilterFunction)(const char* path,
|
||||
const char* interface, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Sets a property monitor for the D-Bus proxy.
|
||||
*
|
||||
* @param proxy the GDBusProxy object which the property monitor is to be set.
|
||||
* @param function Pointer to the callback function that handles property changes.
|
||||
* @param user_data User data, which will be passed to the callback function.
|
||||
* @return Returns TRUE if the monitor was successfully set, otherwise returns FALSE.
|
||||
*/
|
||||
gboolean dbus_proxy_set_property_watch(GDBusProxy* proxy,
|
||||
GDBusPropertyFunction function, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Removes a property monitor from a D-Bus proxy.
|
||||
*
|
||||
* @param proxy the GDBusProxy object whose property monitor is to be removed.
|
||||
* @param destroy Pointer to a destruction function that handles user data.
|
||||
* @return Returns TRUE if the monitor was successfully removed, otherwise returns FALSE.
|
||||
*/
|
||||
gboolean dbus_proxy_remove_property_watch(GDBusProxy* proxy,
|
||||
GDBusDestroyFunction destroy);
|
||||
|
||||
gboolean dbus_proxy_set_removed_watch(GDBusProxy* proxy,
|
||||
GDBusProxyFunction destroy, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Create a new DBus client instance
|
||||
*
|
||||
* This function is used to create a new DBus client instance.
|
||||
*
|
||||
* @param connection Pointer to DBus connection.
|
||||
* @param service Service name, used to identify DBus service.
|
||||
* @param path Path, used to identify the path of DBus object.
|
||||
*
|
||||
* @return Returns a pointer to the newly created GDBusClient instance.
|
||||
*/
|
||||
GDBusClient* dbus_client_new(DBusConnection* connection,
|
||||
const char* service, const char* path);
|
||||
|
||||
GDBusClient* dbus_client_new_full(DBusConnection* connection,
|
||||
const char* service,
|
||||
const char* path,
|
||||
const char* root_path);
|
||||
|
||||
/**
|
||||
* @brief Increase the reference count of the GDBusClient object.
|
||||
*
|
||||
* @param client The GDBusClient object whose reference count is to be increased.
|
||||
* @return The GDBusClient object after the reference count is increased.
|
||||
*/
|
||||
GDBusClient* dbus_client_ref(GDBusClient* client);
|
||||
|
||||
/**
|
||||
* @brief Decrement the reference count of a GDBusClient object.
|
||||
*
|
||||
* @param client The GDBusClient object whose reference count is to be decremented.
|
||||
*/
|
||||
void dbus_client_unref(GDBusClient* client);
|
||||
|
||||
/**
|
||||
* @brief Set the connection monitoring function of the D-Bus client.
|
||||
*
|
||||
* @param client Pointer to the GDBusClient instance.
|
||||
* @param function Pointer to the function of type GDBusWatchFunction, which will be
|
||||
* called when there is a new D-Bus connection.
|
||||
* @param user_data caller data, which will be passed to the caller when callback
|
||||
* @return If the setting is successful, return a true value of type gboolean; otherwise,
|
||||
* return a false value.
|
||||
*/
|
||||
gboolean dbus_client_set_connect_watch(GDBusClient* client, GDBusWatchFunction function,
|
||||
void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Set the disconnection monitoring function of the D-Bus client.
|
||||
*
|
||||
* @param client Pointer to the GDBusClient instance.
|
||||
* @param function Pointer to the function of type GDBusWatchFunction, which will be
|
||||
* called when the D-Bus connection is disconnected.
|
||||
* @param user_data caller data will be passed to the caller when calling the function.
|
||||
* @return If the setting is successful, return a true value of type gboolean; otherwise,
|
||||
* return a false value.
|
||||
*/
|
||||
gboolean dbus_client_set_disconnect_watch(GDBusClient* client,
|
||||
GDBusWatchFunction function, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Set the signal monitoring function of the D-Bus client
|
||||
*
|
||||
* This function is used to set the signal monitoring function of the D-Bus client.
|
||||
* When the client receives a D-Bus signal, the function will be called.
|
||||
*
|
||||
* @param client Pointer to the D-Bus client
|
||||
* @param function Points to the function that processes the D-Bus signal
|
||||
* @param user_data caller data will be passed to the caller when calling the function
|
||||
*
|
||||
* @return If the setting is successful, return gboolean as TRUE, otherwise return FALSE
|
||||
*/
|
||||
gboolean dbus_client_set_signal_watch(GDBusClient* client,
|
||||
GDBusMessageFunction function, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Set the preparation function and user data of the DBus client
|
||||
*
|
||||
* This function is used to set the preparation function and user data of the DBus client.
|
||||
* The preparation function will be called when the DBus client is ready, and the user
|
||||
* data can be passed to this function.
|
||||
*
|
||||
* @param client Pointer to the DBus client
|
||||
* @param ready Preparation function, which will be called when the DBus client is ready
|
||||
* @param user_data User data, which can be passed to the preparation function
|
||||
*
|
||||
* @return gboolean If the setting is successful, it returns TRUE, otherwise it returns FALSE
|
||||
*/
|
||||
gboolean dbus_client_set_ready_watch(GDBusClient* client,
|
||||
GDBusClientFunction ready, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Set the proxy handler function
|
||||
*
|
||||
* This function is used to set the proxy handler function of the D-Bus client.
|
||||
*
|
||||
* @param client Pointer to the GDBusClient instance.
|
||||
* @param proxy_added Callback function when the proxy is added.
|
||||
* @param proxy_removed Callback function when the proxy is removed.
|
||||
* @param proxy_property_filter Callback function for proxy property filtering.
|
||||
* @param property_changed Callback function when the property is changed.
|
||||
* @param user_data caller data, which will be used in the callback function.
|
||||
* @return If the setting is successful, the return gboolean is TRUE, otherwise
|
||||
* it returns FALSE.
|
||||
*/
|
||||
gboolean dbus_client_set_proxy_handlers(GDBusClient* client,
|
||||
GDBusProxyFunction proxy_added,
|
||||
GDBusProxyFunction proxy_removed,
|
||||
GDBusProxyPropertyFilterFunction proxy_property_filter,
|
||||
GDBusPropertyFunction property_changed,
|
||||
void* user_data);
|
||||
|
||||
/**
|
||||
* @brief Set the proxy filter function
|
||||
*
|
||||
* This function is used to set the proxy filter function of the D-Bus client.
|
||||
*
|
||||
* @param client Pointer to the GDBusClient instance.
|
||||
* @param proxy_filter Callback function of the proxy filter.
|
||||
* @param user_data caller data, which will be used in the callback function.
|
||||
* @return If the setting is successful, the return gboolean is TRUE, otherwise
|
||||
* it returns FALSE.
|
||||
*/
|
||||
gboolean dbus_client_set_proxy_filter(GDBusClient* client,
|
||||
GDBusProxyFilterFunction proxy_filter,
|
||||
void* user_data);
|
||||
|
||||
/**
|
||||
* Adds a service watch for the specified name.
|
||||
* @param client The DBus client instance
|
||||
* @param name The service name to watch
|
||||
* @param connect Callback when service connects
|
||||
* @param disconnect Callback when service disconnects
|
||||
* @param user_data User data passed to callbacks
|
||||
* @param destroy Destroy notification callback
|
||||
* @return Watch ID
|
||||
*/
|
||||
guint dbus_client_add_service_watch(GDBusClient* client, const char* name,
|
||||
GDBusWatchFunction connect, GDBusWatchFunction disconnect,
|
||||
void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* Adds a watch for service disconnection only.
|
||||
* @param client The DBus client instance
|
||||
* @param name The service name to watch
|
||||
* @param function Callback when service disconnects
|
||||
* @param user_data User data passed to callback
|
||||
* @param destroy Destroy notification callback
|
||||
* @return Watch ID
|
||||
*/
|
||||
guint dbus_client_add_service_disconnect_watch(GDBusClient* client, const char* name,
|
||||
GDBusWatchFunction function, void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* Adds a signal watch with detailed matching criteria.
|
||||
* @param client The DBus client instance
|
||||
* @param sender The sender name to match
|
||||
* @param path The object path to match
|
||||
* @param interface The interface name to match
|
||||
* @param member The member name to match
|
||||
* @param function Callback when signal is received
|
||||
* @param user_data User data passed to callback
|
||||
* @param destroy Destroy notification callback
|
||||
* @return Watch ID
|
||||
*/
|
||||
guint dbus_client_add_signal_watch(GDBusClient* client,const char* sender,
|
||||
const char* path, const char* interface, const char* member,
|
||||
GDBusSignalFunction function, void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* Adds a properties change watch.
|
||||
* @param client The DBus client instance
|
||||
* @param sender The sender name to match
|
||||
* @param path The object path to match
|
||||
* @param interface The interface name to match
|
||||
* @param function Callback when properties change
|
||||
* @param user_data User data passed to callback
|
||||
* @param destroy Destroy notification callback
|
||||
* @return Watch ID
|
||||
*/
|
||||
guint dbus_client_add_properties_watch(GDBusClient* client,
|
||||
const char* sender, const char* path, const char* interface,
|
||||
GDBusSignalFunction function, void* user_data, GDBusDestroyFunction destroy);
|
||||
|
||||
/**
|
||||
* Removes a previously added watch.
|
||||
* @param client The DBus client instance
|
||||
* @param tag The watch ID to remove
|
||||
* @return TRUE if watch was found and removed
|
||||
*/
|
||||
gboolean dbus_client_remove_watch(GDBusClient* client, guint tag);
|
||||
|
||||
/**
|
||||
* Removes all watches from the client.
|
||||
* @param client The DBus client instance
|
||||
*/
|
||||
void dbus_client_remove_all_watches(GDBusClient* client);
|
||||
|
||||
/**
|
||||
* Adds a watch for client disconnection.
|
||||
* @param client The DBus client instance
|
||||
* @param function Callback when client disconnects
|
||||
* @param user_data User data passed to callback
|
||||
* @param destroy Destroy notification callback
|
||||
* @return Watch ID
|
||||
*/
|
||||
gboolean dbus_client_add_disconnect_watch(GDBusClient* client,
|
||||
GDBusWatchFunction function, void* user_data, DBusFreeFunction destroy);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GDBUS_H */
|
||||
512
gdbus/mainloop.c
512
gdbus/mainloop.c
|
|
@ -1,512 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Xiaomi Technologies Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of the Xiaomi project.
|
||||
*
|
||||
* This source code is licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gdbus-internal.h"
|
||||
|
||||
struct idle_handler {
|
||||
uv_idle_t handle;
|
||||
DBusConnection* conn;
|
||||
};
|
||||
|
||||
struct timeout_handler {
|
||||
uv_timer_t handle;
|
||||
DBusTimeout* timeout;
|
||||
};
|
||||
|
||||
struct dbus_watch_info {
|
||||
uv_poll_t* handle;
|
||||
DBusWatch* read_watch;
|
||||
DBusWatch* write_watch;
|
||||
DBusConnection* conn;
|
||||
};
|
||||
|
||||
static void close_cb(uv_handle_t* handle)
|
||||
{
|
||||
free(handle->data);
|
||||
}
|
||||
|
||||
static void message_dispatch(uv_idle_t* handle)
|
||||
{
|
||||
struct idle_handler* handler = handle->data;
|
||||
DBusConnection* conn = handler->conn;
|
||||
|
||||
/* Dispatch messages */
|
||||
while (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS)
|
||||
;
|
||||
|
||||
dbus_connection_unref(conn);
|
||||
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
static inline void queue_dispatch(DBusConnection* conn,
|
||||
DBusDispatchStatus status)
|
||||
{
|
||||
if (status == DBUS_DISPATCH_DATA_REMAINS) {
|
||||
struct idle_handler* handler;
|
||||
|
||||
handler = calloc(1, sizeof(struct idle_handler));
|
||||
if (handler == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uv_idle_init(uv_default_loop(), &handler->handle) != 0) {
|
||||
free(handler);
|
||||
return;
|
||||
}
|
||||
|
||||
handler->conn = dbus_connection_ref(conn);
|
||||
handler->handle.data = handler;
|
||||
if (uv_idle_start(&handler->handle, message_dispatch) != 0) {
|
||||
dbus_connection_unref(conn);
|
||||
uv_close((uv_handle_t*)&handler->handle, close_cb);
|
||||
free(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void watch_func(uv_poll_t* handle, int state, int events)
|
||||
{
|
||||
struct dbus_watch_info* info = handle->data;
|
||||
unsigned int flags = 0;
|
||||
DBusDispatchStatus status;
|
||||
DBusConnection* conn;
|
||||
|
||||
if (events & UV_READABLE)
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
if (events & UV_WRITABLE)
|
||||
flags |= DBUS_WATCH_WRITABLE;
|
||||
if (events & UV_DISCONNECT)
|
||||
flags |= DBUS_WATCH_HANGUP;
|
||||
if (events & POLLERR)
|
||||
flags |= DBUS_WATCH_ERROR;
|
||||
|
||||
/* Protect connection from being destroyed by dbus_watch_handle */
|
||||
conn = dbus_connection_ref(info->conn);
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE && info->read_watch != NULL)
|
||||
dbus_watch_handle(info->read_watch, flags);
|
||||
if (flags & DBUS_WATCH_WRITABLE && info->write_watch != NULL)
|
||||
dbus_watch_handle(info->write_watch, flags);
|
||||
|
||||
status = dbus_connection_get_dispatch_status(conn);
|
||||
queue_dispatch(conn, status);
|
||||
|
||||
dbus_connection_unref(conn);
|
||||
}
|
||||
|
||||
static void close_watch_info_handler_cb(uv_handle_t* handle)
|
||||
{
|
||||
struct dbus_watch_info* info = handle->data;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
if (info->read_watch) {
|
||||
dbus_watch_set_data(info->read_watch, NULL, NULL);
|
||||
info->read_watch = NULL;
|
||||
}
|
||||
if (info->write_watch) {
|
||||
dbus_watch_set_data(info->write_watch, NULL, NULL);
|
||||
info->write_watch = NULL;
|
||||
}
|
||||
|
||||
free(info->handle);
|
||||
info->handle = NULL;
|
||||
}
|
||||
|
||||
static void watch_info_free_read(void* data)
|
||||
{
|
||||
struct dbus_watch_info* info = data;
|
||||
|
||||
if (info != NULL && info->read_watch != NULL) {
|
||||
info->read_watch = NULL;
|
||||
|
||||
/**
|
||||
* libdbus maybe call read watch free cb, not from remove watch.
|
||||
* need close uv hander when read and watch both null.
|
||||
*/
|
||||
if (info->write_watch == NULL && info->handle != NULL)
|
||||
uv_close((uv_handle_t*)info->handle, close_watch_info_handler_cb);
|
||||
}
|
||||
}
|
||||
|
||||
static void watch_info_free_write(void* data)
|
||||
{
|
||||
struct dbus_watch_info* info = data;
|
||||
|
||||
if (info != NULL && info->write_watch != NULL) {
|
||||
info->write_watch = NULL;
|
||||
|
||||
/**
|
||||
* libdbus maybe call write watch free cb, not from remove watch.
|
||||
* need close uv hander when read and watch both null.
|
||||
*/
|
||||
if (info->read_watch == NULL && info->handle != NULL)
|
||||
uv_close((uv_handle_t*)info->handle, close_watch_info_handler_cb);
|
||||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t add_watch(DBusWatch* watch, void* data)
|
||||
{
|
||||
struct dbus_watch_info* watch_info = data;
|
||||
int cond = UV_DISCONNECT;
|
||||
int flags = 0;
|
||||
|
||||
if (!dbus_watch_get_enabled(watch))
|
||||
return TRUE;
|
||||
|
||||
flags = dbus_watch_get_flags(watch);
|
||||
if (flags & DBUS_WATCH_READABLE) {
|
||||
dbus_watch_set_data(watch, watch_info, watch_info_free_read);
|
||||
watch_info->read_watch = watch;
|
||||
}
|
||||
if (flags & DBUS_WATCH_WRITABLE) {
|
||||
dbus_watch_set_data(watch, watch_info, watch_info_free_write);
|
||||
watch_info->write_watch = watch;
|
||||
}
|
||||
|
||||
if (watch_info->read_watch != NULL && watch != watch_info->read_watch)
|
||||
flags |= dbus_watch_get_flags(watch_info->read_watch);
|
||||
if (watch_info->write_watch != NULL && watch != watch_info->write_watch)
|
||||
flags |= dbus_watch_get_flags(watch_info->write_watch);
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
cond |= UV_READABLE;
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
cond |= UV_WRITABLE;
|
||||
|
||||
if (!watch_info->handle) {
|
||||
watch_info->handle = calloc(1, sizeof(uv_poll_t));
|
||||
if (!watch_info->handle)
|
||||
return FALSE;
|
||||
|
||||
int fd = dbus_watch_get_unix_fd(watch);
|
||||
if (uv_poll_init(uv_default_loop(), watch_info->handle, fd) != 0) {
|
||||
free(watch_info->handle);
|
||||
watch_info->handle = NULL;
|
||||
dbus_watch_set_data(watch, NULL, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
watch_info->handle->data = watch_info;
|
||||
}
|
||||
|
||||
if (uv_poll_start(watch_info->handle, cond, watch_func) != 0) {
|
||||
uv_close((uv_handle_t*)watch_info->handle, close_watch_info_handler_cb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void remove_watch(DBusWatch* watch, void* data)
|
||||
{
|
||||
int flags = 0;
|
||||
int cond = 0;
|
||||
struct dbus_watch_info* info = data;
|
||||
|
||||
/* If the watch is still enabled, we treat this as a toggle */
|
||||
if (dbus_watch_get_enabled(watch))
|
||||
return;
|
||||
|
||||
if (info->read_watch == watch && info->write_watch != NULL) {
|
||||
/* remove watch is read, keep write flag if write watch is valid */
|
||||
flags = dbus_watch_get_flags(info->write_watch);
|
||||
} else if (info->write_watch == watch && info->read_watch != NULL) {
|
||||
/* remove watch is write, keep read flag if read watch is valid */
|
||||
flags = dbus_watch_get_flags(info->read_watch);
|
||||
}
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
cond |= UV_READABLE;
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
cond |= UV_WRITABLE;
|
||||
|
||||
if (cond != 0) {
|
||||
cond |= UV_DISCONNECT;
|
||||
if (uv_poll_start(info->handle, cond, watch_func) != 0) {
|
||||
uv_close((uv_handle_t*)info->handle, close_watch_info_handler_cb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* will trigger watch_info_free_read/write() */
|
||||
dbus_watch_set_data(watch, NULL, NULL);
|
||||
}
|
||||
|
||||
static void watch_toggled(DBusWatch* watch, void* data)
|
||||
{
|
||||
/* Because we just exit on OOM, enable/disable is
|
||||
* no different from add/remove */
|
||||
if (dbus_watch_get_enabled(watch))
|
||||
add_watch(watch, data);
|
||||
else
|
||||
remove_watch(watch, data);
|
||||
}
|
||||
|
||||
static void timeout_handler_dispatch(uv_timer_t* handle)
|
||||
{
|
||||
struct timeout_handler* handler = handle->data;
|
||||
|
||||
/* if not enabled should not be polled by the main loop */
|
||||
if (dbus_timeout_get_enabled(handler->timeout))
|
||||
dbus_timeout_handle(handler->timeout);
|
||||
}
|
||||
|
||||
static void timeout_handler_free(void* data)
|
||||
{
|
||||
struct timeout_handler* handler = data;
|
||||
|
||||
uv_close((uv_handle_t*)&handler->handle, close_cb);
|
||||
}
|
||||
|
||||
static dbus_bool_t add_timeout(DBusTimeout* timeout, void* data)
|
||||
{
|
||||
int interval = dbus_timeout_get_interval(timeout);
|
||||
struct timeout_handler* handler;
|
||||
|
||||
if (!dbus_timeout_get_enabled(timeout))
|
||||
return TRUE;
|
||||
|
||||
handler = calloc(1, sizeof(struct timeout_handler));
|
||||
if (handler == NULL)
|
||||
return FALSE;
|
||||
|
||||
handler->timeout = timeout;
|
||||
|
||||
dbus_timeout_set_data(timeout, handler, timeout_handler_free);
|
||||
|
||||
if (uv_timer_init(uv_default_loop(), &handler->handle) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
handler->handle.data = handler;
|
||||
if (uv_timer_start(&handler->handle, timeout_handler_dispatch, interval, 0) != 0) {
|
||||
uv_close((uv_handle_t*)&handler->handle, close_cb);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
errout:
|
||||
free(handler);
|
||||
dbus_timeout_set_data(timeout, NULL, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void remove_timeout(DBusTimeout* timeout, void* data)
|
||||
{
|
||||
/* will trigger timeout_handler_free() */
|
||||
dbus_timeout_set_data(timeout, NULL, NULL);
|
||||
}
|
||||
|
||||
static void timeout_toggled(DBusTimeout* timeout, void* data)
|
||||
{
|
||||
if (dbus_timeout_get_enabled(timeout))
|
||||
add_timeout(timeout, data);
|
||||
else
|
||||
remove_timeout(timeout, data);
|
||||
}
|
||||
|
||||
static void dispatch_status(DBusConnection* conn,
|
||||
DBusDispatchStatus status, void* data)
|
||||
{
|
||||
if (!dbus_connection_get_is_connected(conn))
|
||||
return;
|
||||
|
||||
queue_dispatch(conn, status);
|
||||
}
|
||||
|
||||
static void dbus_watch_info_free(void* data)
|
||||
{
|
||||
struct dbus_watch_info* info = data;
|
||||
|
||||
if (info != NULL) {
|
||||
dbus_connection_unref(info->conn);
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void setup_dbus_with_main_loop(DBusConnection* conn)
|
||||
{
|
||||
struct dbus_watch_info* info = calloc(1, sizeof(struct dbus_watch_info));
|
||||
if (info == NULL)
|
||||
return;
|
||||
info->conn = dbus_connection_ref(conn);
|
||||
|
||||
dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
|
||||
watch_toggled, info, dbus_watch_info_free);
|
||||
|
||||
dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
|
||||
timeout_toggled, NULL, NULL);
|
||||
|
||||
dbus_connection_set_dispatch_status_function(conn, dispatch_status,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean setup_bus(DBusConnection* conn, const char* name,
|
||||
DBusError* error)
|
||||
{
|
||||
gboolean result;
|
||||
DBusDispatchStatus status;
|
||||
|
||||
if (name != NULL) {
|
||||
result = dbus_request_name(conn, name, error);
|
||||
|
||||
if (error != NULL) {
|
||||
if (dbus_error_is_set(error) == TRUE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (result == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
setup_dbus_with_main_loop(conn);
|
||||
|
||||
status = dbus_connection_get_dispatch_status(conn);
|
||||
queue_dispatch(conn, status);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DBusConnection* dbus_setup_bus(DBusBusType type, const char* name,
|
||||
DBusError* error)
|
||||
{
|
||||
DBusConnection* conn;
|
||||
|
||||
conn = dbus_bus_get(type, error);
|
||||
|
||||
if (error != NULL) {
|
||||
if (dbus_error_is_set(error) == TRUE)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
|
||||
if (setup_bus(conn, name, error) == FALSE) {
|
||||
dbus_connection_unref(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
DBusConnection* dbus_setup_private(DBusBusType type, const char* name,
|
||||
DBusError* error)
|
||||
{
|
||||
DBusConnection* conn;
|
||||
|
||||
conn = dbus_bus_get_private(type, error);
|
||||
|
||||
if (error != NULL) {
|
||||
if (dbus_error_is_set(error) == TRUE)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
|
||||
if (setup_bus(conn, name, error) == FALSE) {
|
||||
dbus_connection_close(conn);
|
||||
dbus_connection_unref(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
gboolean dbus_request_name(DBusConnection* connection, const char* name,
|
||||
DBusError* error)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = dbus_bus_request_name(connection, name,
|
||||
DBUS_NAME_FLAG_DO_NOT_QUEUE, error);
|
||||
|
||||
if (error != NULL) {
|
||||
if (dbus_error_is_set(error) == TRUE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
if (error != NULL)
|
||||
dbus_set_error(error, name, "Name already in use");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct disconnect_data {
|
||||
GDBusWatchFunction function;
|
||||
void* user_data;
|
||||
GDBusWatch* watcher;
|
||||
};
|
||||
|
||||
static gboolean disconnected_signal(DBusConnection* conn,
|
||||
DBusMessage* msg, void* data)
|
||||
{
|
||||
struct disconnect_data* dc_data = data;
|
||||
|
||||
info("Got disconnected from the system message bus");
|
||||
|
||||
dc_data->function(conn, dc_data->user_data);
|
||||
|
||||
dbus_connection_unref(conn);
|
||||
|
||||
dbus_watch_set_connection_state(dc_data->watcher, TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean dbus_client_add_disconnect_watch(GDBusClient* client,
|
||||
GDBusWatchFunction function, void* user_data, DBusFreeFunction destroy)
|
||||
{
|
||||
struct disconnect_data* dc_data;
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(client->dbus_conn, FALSE);
|
||||
|
||||
dc_data = calloc(1, sizeof(struct disconnect_data));
|
||||
if (dc_data == NULL)
|
||||
return FALSE;
|
||||
|
||||
dc_data->function = function;
|
||||
dc_data->user_data = user_data;
|
||||
dc_data->watcher = client->watcher;
|
||||
|
||||
if (dbus_add_signal_watch(client->watcher, NULL, NULL,
|
||||
DBUS_INTERFACE_LOCAL, "Disconnected",
|
||||
disconnected_signal, dc_data, free)
|
||||
== 0) {
|
||||
error("Failed to add watch for D-Bus Disconnected signal");
|
||||
free(dc_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_connection_ref(client->dbus_conn);
|
||||
return TRUE;
|
||||
}
|
||||
2055
gdbus/object.c
2055
gdbus/object.c
File diff suppressed because it is too large
Load Diff
226
gdbus/polkit.c
226
gdbus/polkit.c
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Xiaomi Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "gdbus-internal.h"
|
||||
|
||||
#define POLICY_KIT_DBUS_NAME "org.freedesktop.PolicyKit1"
|
||||
#define POLICY_KIT_INTERFACE "org.freedesktop.PolicyKit1.Authority"
|
||||
#define POLICY_KIT_PATH "/org/freedesktop/PolicyKit1/Authority"
|
||||
#define POLICY_KIT_ACTION "org.freedesktop.policykit.exec"
|
||||
|
||||
typedef enum polkit_interaction_flag {
|
||||
POLKIT_FLAG_NONE = 0x00000000,
|
||||
POLKIT_FLAG_ALLOW = 0x00000001
|
||||
} polkit_interaction_flag;
|
||||
|
||||
typedef struct authorization_context {
|
||||
void (*callback)(dbus_bool_t authorized, void* user_data);
|
||||
void* user_data;
|
||||
} authorization_context;
|
||||
|
||||
typedef struct dict_entry_builder {
|
||||
DBusMessageIter iter;
|
||||
const char* key;
|
||||
const char* value;
|
||||
} dict_entry_builder;
|
||||
|
||||
typedef enum contained_sig_type {
|
||||
SIG_TYPE_EMPTY,
|
||||
SIG_TYPE_VARIANT,
|
||||
} contained_sig_type;
|
||||
|
||||
static const char* init_contained_signature_type(contained_sig_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SIG_TYPE_EMPTY:
|
||||
return DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING
|
||||
DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
|
||||
case SIG_TYPE_VARIANT:
|
||||
return DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING
|
||||
DBUS_TYPE_VARIANT_AS_STRING
|
||||
DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void build_dict_entry(dict_entry_builder* builder)
|
||||
{
|
||||
DBusMessageIter dict, entry, variant;
|
||||
|
||||
dbus_message_iter_open_container(&builder->iter, DBUS_TYPE_ARRAY,
|
||||
init_contained_signature_type(SIG_TYPE_VARIANT), &dict);
|
||||
|
||||
dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
|
||||
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &builder->key);
|
||||
|
||||
dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
|
||||
DBUS_TYPE_STRING_AS_STRING, &variant);
|
||||
dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &builder->value);
|
||||
|
||||
dbus_message_iter_close_container(&entry, &variant);
|
||||
dbus_message_iter_close_container(&dict, &entry);
|
||||
dbus_message_iter_close_container(&builder->iter, &dict);
|
||||
}
|
||||
|
||||
static void build_empty_dict(DBusMessageIter* iter)
|
||||
{
|
||||
DBusMessageIter dict;
|
||||
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
|
||||
init_contained_signature_type(SIG_TYPE_EMPTY), &dict);
|
||||
dbus_message_iter_close_container(iter, &dict);
|
||||
}
|
||||
|
||||
static void build_authorization_arguments(DBusConnection* conn, DBusMessageIter* iter,
|
||||
const char* action, polkit_interaction_flag flags)
|
||||
{
|
||||
const char* bus_name = dbus_bus_get_unique_name(conn);
|
||||
const char* subject_kind = "system-bus-name";
|
||||
const char* cancellation_id = "";
|
||||
DBusMessageIter subject;
|
||||
|
||||
// build main subject
|
||||
dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &subject);
|
||||
dbus_message_iter_append_basic(&subject, DBUS_TYPE_STRING, &subject_kind);
|
||||
|
||||
dict_entry_builder builder = {
|
||||
.iter = subject,
|
||||
.key = "name",
|
||||
.value = bus_name
|
||||
};
|
||||
build_dict_entry(&builder);
|
||||
dbus_message_iter_close_container(iter, &subject);
|
||||
|
||||
// add less parameters
|
||||
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
|
||||
action ? action : POLICY_KIT_ACTION);
|
||||
build_empty_dict(iter);
|
||||
dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &flags);
|
||||
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &cancellation_id);
|
||||
}
|
||||
|
||||
static dbus_bool_t parse_authorization_result(DBusMessageIter* iter)
|
||||
{
|
||||
DBusMessageIter recurse_iter;
|
||||
dbus_bool_t auth = FALSE;
|
||||
|
||||
if (!iter)
|
||||
return FALSE;
|
||||
|
||||
dbus_message_iter_recurse(iter, &recurse_iter);
|
||||
dbus_message_iter_get_basic(&recurse_iter, &auth);
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
static void handle_authorization_reply(DBusPendingCall* call, void* user_data)
|
||||
{
|
||||
authorization_context* context = user_data;
|
||||
DBusMessage* reply = NULL;
|
||||
DBusMessageIter iter;
|
||||
dbus_bool_t authorized = FALSE;
|
||||
|
||||
if (!call || !context)
|
||||
goto cleanup;
|
||||
|
||||
reply = dbus_pending_call_steal_reply(call);
|
||||
if (!reply)
|
||||
goto cleanup;
|
||||
|
||||
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
|
||||
error("Authorization error: %s\n", dbus_message_get_error_name(reply));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!dbus_message_has_signature(reply, "(bba{ss})")) {
|
||||
error("Invalid reply signature\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_init(reply, &iter))
|
||||
goto cleanup;
|
||||
|
||||
authorized = parse_authorization_result(&iter);
|
||||
|
||||
cleanup:
|
||||
if (context != NULL && context->callback) {
|
||||
context->callback(authorized, context->user_data);
|
||||
}
|
||||
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_pending_call_unref(call);
|
||||
}
|
||||
|
||||
int dbus_polkit_check_authorization(DBusConnection* conn,
|
||||
const char* action, gboolean allow_interaction,
|
||||
void (*callback)(dbus_bool_t, void*),
|
||||
void* user_data, int timeout_ms)
|
||||
{
|
||||
DBusMessage* msg;
|
||||
DBusMessageIter iter;
|
||||
DBusPendingCall* pending_call = NULL;
|
||||
polkit_interaction_flag flags;
|
||||
|
||||
if (!conn)
|
||||
return -EINVAL;
|
||||
|
||||
authorization_context* context = calloc(1, sizeof(authorization_context));
|
||||
if (!context)
|
||||
return -ENOMEM;
|
||||
|
||||
msg = dbus_message_new_method_call(POLICY_KIT_DBUS_NAME, POLICY_KIT_PATH,
|
||||
POLICY_KIT_INTERFACE, "CheckAuthorization");
|
||||
if (!msg) {
|
||||
free(context);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
flags = allow_interaction ? POLKIT_FLAG_ALLOW : POLKIT_FLAG_NONE;
|
||||
|
||||
dbus_message_iter_init_append(msg, &iter);
|
||||
build_authorization_arguments(conn, &iter, action, flags);
|
||||
|
||||
if (!dbus_connection_send_with_reply(conn, msg, &pending_call, timeout_ms)) {
|
||||
dbus_message_unref(msg);
|
||||
free(context);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!pending_call) {
|
||||
dbus_message_unref(msg);
|
||||
free(context);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
context->callback = callback;
|
||||
context->user_data = user_data;
|
||||
|
||||
dbus_pending_call_set_notify(pending_call, handle_authorization_reply,
|
||||
context, free);
|
||||
dbus_message_unref(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
995
gdbus/watch.c
995
gdbus/watch.c
|
|
@ -1,995 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Xiaomi Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gdbus-internal.h"
|
||||
|
||||
static DBusHandlerResult message_filter(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data);
|
||||
|
||||
struct GDBusWatch {
|
||||
DBusConnection* conn;
|
||||
guint serial;
|
||||
DBusList* list;
|
||||
gboolean conn_closed;
|
||||
};
|
||||
|
||||
struct service_data {
|
||||
DBusConnection* conn;
|
||||
DBusPendingCall* call;
|
||||
char* name;
|
||||
const char* owner;
|
||||
struct filter_callback* callback;
|
||||
uv_idle_t handle;
|
||||
};
|
||||
|
||||
struct filter_callback {
|
||||
GDBusWatchFunction conn_func;
|
||||
GDBusWatchFunction disc_func;
|
||||
GDBusSignalFunction signal_func;
|
||||
GDBusDestroyFunction destroy_func;
|
||||
struct service_data* data;
|
||||
void* user_data;
|
||||
guint id;
|
||||
};
|
||||
|
||||
struct filter_data {
|
||||
DBusConnection* connection;
|
||||
DBusHandleMessageFunction handle_func;
|
||||
char* name;
|
||||
char* owner;
|
||||
char* path;
|
||||
char* interface;
|
||||
char* member;
|
||||
char* argument;
|
||||
DBusList* callbacks;
|
||||
DBusList* processed;
|
||||
guint name_watch;
|
||||
gboolean lock;
|
||||
gboolean registered;
|
||||
GDBusWatch* watcher;
|
||||
};
|
||||
|
||||
static int strcmp0(const char* str1, const char* str2)
|
||||
{
|
||||
if (str1 == NULL)
|
||||
return -(str1 != str2);
|
||||
|
||||
if (str2 == NULL)
|
||||
return -(str1 != str2);
|
||||
|
||||
return strcmp(str1, str2);
|
||||
}
|
||||
|
||||
static char* strdup0(const char* str)
|
||||
{
|
||||
if (str)
|
||||
return strdup(str);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int get_watch_serial(GDBusWatch* watcher)
|
||||
{
|
||||
return ++watcher->serial;
|
||||
}
|
||||
|
||||
static struct filter_data* filter_data_find_match(DBusConnection* connection,
|
||||
DBusList* listener_list, const char* name, const char* owner,
|
||||
const char* path, const char* interface, const char* member, const char* argument)
|
||||
{
|
||||
DBusList* current;
|
||||
|
||||
for (current = _dbus_list_get_first_link(&listener_list); current != NULL;
|
||||
current = _dbus_list_get_next_link(&listener_list, current)) {
|
||||
struct filter_data* data = current->data;
|
||||
|
||||
if (connection != data->connection)
|
||||
continue;
|
||||
|
||||
if (strcmp0(name, data->name) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp0(owner, data->owner) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp0(path, data->path) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp0(interface, data->interface) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp0(member, data->member) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp0(argument, data->argument) != 0)
|
||||
continue;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct filter_data* filter_data_find(DBusConnection* connection, DBusList* listener_list)
|
||||
{
|
||||
DBusList* current;
|
||||
|
||||
for (current = _dbus_list_get_first_link(&listener_list); current != NULL;
|
||||
current = _dbus_list_get_next_link(&listener_list, current)) {
|
||||
struct filter_data* data = current->data;
|
||||
|
||||
if (connection != data->connection)
|
||||
continue;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void format_rule(struct filter_data* data, char* rule, size_t size)
|
||||
{
|
||||
const char* sender;
|
||||
int offset;
|
||||
|
||||
offset = snprintf(rule, size, "type='signal'");
|
||||
sender = data->name ?: data->owner;
|
||||
|
||||
if (sender)
|
||||
offset += snprintf(rule + offset, size - offset,
|
||||
",sender='%s'", sender);
|
||||
if (data->path)
|
||||
offset += snprintf(rule + offset, size - offset,
|
||||
",path='%s'", data->path);
|
||||
if (data->interface)
|
||||
offset += snprintf(rule + offset, size - offset,
|
||||
",interface='%s'", data->interface);
|
||||
if (data->member)
|
||||
offset += snprintf(rule + offset, size - offset,
|
||||
",member='%s'", data->member);
|
||||
if (data->argument)
|
||||
snprintf(rule + offset, size - offset,
|
||||
",arg0='%s'", data->argument);
|
||||
}
|
||||
|
||||
static gboolean add_match(struct filter_data* data,
|
||||
DBusHandleMessageFunction filter)
|
||||
{
|
||||
DBusError err;
|
||||
char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
|
||||
|
||||
format_rule(data, rule, sizeof(rule));
|
||||
dbus_error_init(&err);
|
||||
|
||||
dbus_bus_add_match(data->connection, rule, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
error("Adding match rule \"%s\" failed: %s", rule,
|
||||
err.message);
|
||||
dbus_error_free(&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data->handle_func = filter;
|
||||
data->registered = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean remove_match(struct filter_data* data)
|
||||
{
|
||||
DBusError err;
|
||||
char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
|
||||
|
||||
if (data->watcher->conn_closed) {
|
||||
/* If the connection is disconnected, we don't need to remove the match */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
format_rule(data, rule, sizeof(rule));
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
dbus_bus_remove_match(data->connection, rule, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
error("GDBUS Removing owner match rule for %s failed: %s",
|
||||
rule, err.message);
|
||||
dump_stack();
|
||||
dbus_error_free(&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void filter_data_free(struct filter_data* data, DBusList* listener_list)
|
||||
{
|
||||
DBusList* l;
|
||||
|
||||
/* Remove filter if there are no listeners left for the connection */
|
||||
if (filter_data_find(data->connection, listener_list) == NULL) {
|
||||
dbus_connection_remove_filter(data->connection, message_filter,
|
||||
data->watcher);
|
||||
}
|
||||
|
||||
for (l = _dbus_list_get_first_link(&data->callbacks); l != NULL;
|
||||
l = _dbus_list_get_next_link(&data->callbacks, l))
|
||||
free(l->data);
|
||||
|
||||
_dbus_list_clear(&data->callbacks);
|
||||
dbus_remove_watch(data->watcher, data->name_watch);
|
||||
free(data->name);
|
||||
free(data->owner);
|
||||
free(data->path);
|
||||
free(data->interface);
|
||||
free(data->member);
|
||||
free(data->argument);
|
||||
|
||||
/* no listeners left for the connection */
|
||||
if (_dbus_list_get_last(&listener_list) == NULL) {
|
||||
free_dbus_watch(data->watcher);
|
||||
}
|
||||
dbus_connection_unref(data->connection);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static struct filter_data* filter_data_get(GDBusWatch* watcher,
|
||||
DBusHandleMessageFunction filter,
|
||||
const char* sender, const char* path, const char* interface,
|
||||
const char* member, const char* argument)
|
||||
{
|
||||
struct filter_data* data;
|
||||
const char *name = NULL, *owner = NULL;
|
||||
|
||||
if (filter_data_find(watcher->conn, watcher->list) == NULL) {
|
||||
if (!dbus_connection_add_filter(watcher->conn,
|
||||
message_filter, watcher, NULL)) {
|
||||
error("dbus_connection_add_filter() failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sender != NULL) {
|
||||
if (sender[0] == ':')
|
||||
owner = sender;
|
||||
else
|
||||
name = sender;
|
||||
}
|
||||
|
||||
data = filter_data_find_match(watcher->conn, watcher->list, name, owner, path,
|
||||
interface, member, argument);
|
||||
if (data)
|
||||
return data;
|
||||
|
||||
data = calloc(1, sizeof(struct filter_data));
|
||||
|
||||
data->connection = dbus_connection_ref(watcher->conn);
|
||||
data->name = strdup0(name);
|
||||
data->owner = strdup0(owner);
|
||||
data->path = strdup0(path);
|
||||
data->interface = strdup0(interface);
|
||||
data->member = strdup0(member);
|
||||
data->argument = strdup0(argument);
|
||||
data->watcher = watcher;
|
||||
|
||||
if (!add_match(data, filter)) {
|
||||
dbus_connection_unref(data->connection);
|
||||
free(data->name);
|
||||
free(data->owner);
|
||||
free(data->path);
|
||||
free(data->interface);
|
||||
free(data->member);
|
||||
free(data->argument);
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_list_append(&watcher->list, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct filter_callback* filter_data_find_callback(
|
||||
struct filter_data* data,
|
||||
guint id)
|
||||
{
|
||||
DBusList* l;
|
||||
|
||||
for (l = _dbus_list_get_first_link(&data->callbacks); l != NULL;
|
||||
l = _dbus_list_get_next_link(&data->callbacks, l)) {
|
||||
struct filter_callback* cb = l->data;
|
||||
if (cb->id == id)
|
||||
return cb;
|
||||
}
|
||||
for (l = _dbus_list_get_first_link(&data->processed); l != NULL;
|
||||
l = _dbus_list_get_next_link(&data->processed, l)) {
|
||||
struct filter_callback* cb = l->data;
|
||||
if (cb->id == id)
|
||||
return cb;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void filter_data_call_and_free(struct filter_data* data, DBusList* listener_list)
|
||||
{
|
||||
DBusList* l;
|
||||
|
||||
for (l = _dbus_list_get_first_link(&data->callbacks); l != NULL;
|
||||
l = _dbus_list_get_next_link(&data->callbacks, l)) {
|
||||
struct filter_callback* cb = l->data;
|
||||
if (cb->disc_func)
|
||||
cb->disc_func(data->connection, cb->user_data);
|
||||
if (cb->destroy_func)
|
||||
cb->destroy_func(cb->user_data);
|
||||
}
|
||||
|
||||
filter_data_free(data, listener_list);
|
||||
}
|
||||
|
||||
static struct filter_callback* filter_data_add_callback(
|
||||
struct filter_data* data,
|
||||
GDBusWatchFunction connect,
|
||||
GDBusWatchFunction disconnect,
|
||||
GDBusSignalFunction signal,
|
||||
GDBusDestroyFunction destroy,
|
||||
guint watch_id,
|
||||
void* user_data)
|
||||
{
|
||||
struct filter_callback* cb = NULL;
|
||||
|
||||
cb = calloc(1, sizeof(struct filter_callback));
|
||||
|
||||
cb->conn_func = connect;
|
||||
cb->disc_func = disconnect;
|
||||
cb->signal_func = signal;
|
||||
cb->destroy_func = destroy;
|
||||
cb->user_data = user_data;
|
||||
cb->id = watch_id;
|
||||
|
||||
if (data->lock)
|
||||
_dbus_list_append(&data->processed, cb);
|
||||
else
|
||||
_dbus_list_append(&data->callbacks, cb);
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
static void close_cb(uv_handle_t* handle)
|
||||
{
|
||||
free(handle->data);
|
||||
}
|
||||
|
||||
static void service_data_free(struct service_data* data)
|
||||
{
|
||||
struct filter_callback* callback = data->callback;
|
||||
|
||||
dbus_connection_unref(data->conn);
|
||||
|
||||
if (data->call)
|
||||
dbus_pending_call_unref(data->call);
|
||||
|
||||
free(data->name);
|
||||
callback->data = NULL;
|
||||
|
||||
uv_close((uv_handle_t*)&data->handle, close_cb);
|
||||
}
|
||||
|
||||
/* Returns TRUE if data is freed */
|
||||
static gboolean filter_data_remove_callback(struct filter_data* data,
|
||||
struct filter_callback* cb)
|
||||
{
|
||||
_dbus_list_remove(&data->callbacks, cb);
|
||||
_dbus_list_remove(&data->processed, cb);
|
||||
|
||||
/* Cancel pending operations */
|
||||
if (cb->data) {
|
||||
if (cb->data->call)
|
||||
dbus_pending_call_cancel(cb->data->call);
|
||||
service_data_free(cb->data);
|
||||
}
|
||||
|
||||
if (cb->destroy_func)
|
||||
cb->destroy_func(cb->user_data);
|
||||
|
||||
free(cb);
|
||||
|
||||
/* Don't remove the filter if other callbacks exist or data is lock
|
||||
* processing callbacks */
|
||||
if (data->callbacks || data->lock)
|
||||
return FALSE;
|
||||
|
||||
if (data->registered && !remove_match(data))
|
||||
return FALSE;
|
||||
|
||||
_dbus_list_remove(&data->watcher->list, data);
|
||||
filter_data_free(data, data->watcher->list);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DBusHandlerResult signal_filter(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data)
|
||||
{
|
||||
struct filter_data* data = user_data;
|
||||
struct filter_callback* cb;
|
||||
|
||||
while (data->callbacks) {
|
||||
cb = data->callbacks->data;
|
||||
|
||||
if (cb->signal_func && !cb->signal_func(connection, message, cb->user_data)) {
|
||||
if (filter_data_remove_callback(data, cb))
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if the watch was removed/freed by the callback
|
||||
* function */
|
||||
if (_dbus_list_find_last(&data->callbacks, cb) == NULL)
|
||||
continue;
|
||||
|
||||
_dbus_list_remove(&data->callbacks, cb);
|
||||
_dbus_list_append(&data->processed, cb);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static void update_name_cache(DBusList* listener_list, const char* name, const char* owner)
|
||||
{
|
||||
DBusList* l;
|
||||
|
||||
for (l = _dbus_list_get_first_link(&listener_list); l != NULL;
|
||||
l = _dbus_list_get_next_link(&listener_list, l)) {
|
||||
struct filter_data* data = l->data;
|
||||
|
||||
if (strcmp0(data->name, name) != 0)
|
||||
continue;
|
||||
|
||||
free(data->owner);
|
||||
data->owner = strdup0(owner);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* check_name_cache(DBusList* listener_list, const char* name)
|
||||
{
|
||||
DBusList* l;
|
||||
|
||||
for (l = _dbus_list_get_first_link(&listener_list); l != NULL;
|
||||
l = _dbus_list_get_next_link(&listener_list, l)) {
|
||||
struct filter_data* data = l->data;
|
||||
|
||||
if (strcmp0(data->name, name) != 0)
|
||||
continue;
|
||||
|
||||
return data->owner;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusHandlerResult service_filter(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data)
|
||||
{
|
||||
struct filter_data* data = user_data;
|
||||
struct filter_callback* cb;
|
||||
char *name, *old, *new;
|
||||
|
||||
if (!dbus_message_get_args(message, NULL,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &old,
|
||||
DBUS_TYPE_STRING, &new,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
error("Invalid arguments for NameOwnerChanged signal");
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
update_name_cache(data->watcher->list, name, new);
|
||||
|
||||
while (data->callbacks) {
|
||||
cb = data->callbacks->data;
|
||||
|
||||
if (*new == '\0') {
|
||||
if (cb->disc_func)
|
||||
cb->disc_func(connection, cb->user_data);
|
||||
} else {
|
||||
if (cb->conn_func)
|
||||
cb->conn_func(connection, cb->user_data);
|
||||
}
|
||||
|
||||
/* Check if the watch was removed/freed by the callback
|
||||
* function */
|
||||
if (_dbus_list_find_last(&data->callbacks, cb) == NULL)
|
||||
continue;
|
||||
|
||||
/* Only auto remove if it is a bus name watch */
|
||||
if (data->argument[0] == ':' && (cb->conn_func == NULL || cb->disc_func == NULL)) {
|
||||
if (filter_data_remove_callback(data, cb))
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
_dbus_list_remove(&data->callbacks, cb);
|
||||
_dbus_list_append(&data->processed, cb);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static bool process_signal_message(DBusMessage* message,
|
||||
const char** sender, const char** path,
|
||||
const char** iface, const char** member,
|
||||
const char** arg)
|
||||
{
|
||||
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
|
||||
return false;
|
||||
|
||||
*sender = dbus_message_get_sender(message);
|
||||
*path = dbus_message_get_path(message);
|
||||
*iface = dbus_message_get_interface(message);
|
||||
*member = dbus_message_get_member(message);
|
||||
if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, arg, DBUS_TYPE_INVALID))
|
||||
*arg = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
static int filter_data_match(const char* str1, const char* data_param)
|
||||
{
|
||||
if (data_param == NULL)
|
||||
return 0;
|
||||
|
||||
if (str1 == NULL)
|
||||
return -1;
|
||||
|
||||
return strcmp(str1, data_param);
|
||||
}
|
||||
|
||||
static gboolean match_listener_data(struct filter_data* data, DBusConnection* connection,
|
||||
const char* sender, const char* path,
|
||||
const char* iface, const char* member, const char* arg)
|
||||
{
|
||||
if (connection != data->connection)
|
||||
return FALSE;
|
||||
|
||||
if (filter_data_match(sender, data->owner) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (filter_data_match(path, data->path) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (filter_data_match(iface, data->interface) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (filter_data_match(member, data->member) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (filter_data_match(arg, data->argument) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void process_listener_callbacks(struct filter_data* data, DBusConnection* connection,
|
||||
DBusMessage* message)
|
||||
{
|
||||
|
||||
if (!data->handle_func)
|
||||
return;
|
||||
|
||||
data->lock = TRUE;
|
||||
data->handle_func(connection, message, data);
|
||||
data->callbacks = data->processed;
|
||||
data->processed = NULL;
|
||||
data->lock = FALSE;
|
||||
}
|
||||
|
||||
static void process_listeners(DBusList* listener_list, DBusConnection* connection,
|
||||
DBusMessage* message, DBusList** delete_listener, const char* sender,
|
||||
const char* path, const char* iface, const char* member, const char* arg)
|
||||
{
|
||||
DBusList* current;
|
||||
struct filter_data* data;
|
||||
|
||||
for (current = _dbus_list_get_first_link(&listener_list); current;
|
||||
current = _dbus_list_get_next_link(&listener_list, current)) {
|
||||
data = current->data;
|
||||
|
||||
if (!match_listener_data(data, connection, sender,
|
||||
path, iface, member, arg))
|
||||
continue;
|
||||
|
||||
process_listener_callbacks(data, connection, message);
|
||||
|
||||
if (!data->callbacks)
|
||||
_dbus_list_prepend(delete_listener, current);
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_listeners(DBusList* delete_listener, GDBusWatch* watcher)
|
||||
{
|
||||
DBusList* current;
|
||||
struct filter_data* data;
|
||||
|
||||
for (current = _dbus_list_get_first_link(&delete_listener); current;
|
||||
current = _dbus_list_get_next_link(&delete_listener, current)) {
|
||||
DBusList* l = current->data;
|
||||
data = l->data;
|
||||
|
||||
/* Has any other callback added callbacks back to this data? */
|
||||
if (data->callbacks)
|
||||
continue;
|
||||
|
||||
remove_match(data);
|
||||
_dbus_list_remove_link(&watcher->list, l);
|
||||
filter_data_free(data, watcher->list);
|
||||
}
|
||||
_dbus_list_clear(&delete_listener);
|
||||
}
|
||||
|
||||
static DBusHandlerResult message_filter(DBusConnection* connection,
|
||||
DBusMessage* message, void* user_data)
|
||||
{
|
||||
const char *sender, *path, *iface, *member, *arg = NULL;
|
||||
DBusList* delete_listener = NULL;
|
||||
GDBusWatch* watcher = user_data;
|
||||
|
||||
if (!process_signal_message(message, &sender, &path,
|
||||
&iface, &member, &arg))
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
process_listeners(watcher->list, connection, message, &delete_listener,
|
||||
sender, path, iface, member, arg);
|
||||
|
||||
if (delete_listener)
|
||||
cleanup_listeners(delete_listener, watcher);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static void update_service(uv_idle_t* handle)
|
||||
{
|
||||
struct service_data* data = handle->data;
|
||||
struct filter_callback* cb = data->callback;
|
||||
DBusConnection* conn;
|
||||
|
||||
conn = dbus_connection_ref(data->conn);
|
||||
service_data_free(data);
|
||||
|
||||
if (cb->conn_func)
|
||||
cb->conn_func(conn, cb->user_data);
|
||||
|
||||
dbus_connection_unref(conn);
|
||||
}
|
||||
|
||||
static void service_reply(DBusPendingCall* call, void* user_data)
|
||||
{
|
||||
struct service_data* data = user_data;
|
||||
DBusMessage* reply;
|
||||
DBusError err;
|
||||
|
||||
reply = dbus_pending_call_steal_reply(call);
|
||||
if (reply == NULL)
|
||||
return;
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
if (dbus_set_error_from_message(&err, reply))
|
||||
goto fail;
|
||||
|
||||
if (dbus_message_get_args(reply, &err, DBUS_TYPE_STRING,
|
||||
&data->owner, DBUS_TYPE_INVALID)
|
||||
== FALSE)
|
||||
goto fail;
|
||||
|
||||
update_service(&data->handle);
|
||||
|
||||
goto done;
|
||||
|
||||
fail:
|
||||
error("service_reply fail: %s", err.message);
|
||||
dbus_error_free(&err);
|
||||
service_data_free(data);
|
||||
done:
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
static struct service_data* create_service_data(DBusConnection* conn,
|
||||
const char* name,
|
||||
struct filter_callback* cb)
|
||||
{
|
||||
struct service_data* data = calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
error("%s: malloc failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->conn = dbus_connection_ref(conn);
|
||||
data->name = strdup0(name);
|
||||
data->callback = cb;
|
||||
cb->data = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
static bool init_uv_handle(struct service_data* data)
|
||||
{
|
||||
if (uv_idle_init(uv_default_loop(), &data->handle) != 0) {
|
||||
error("%s: uv_idle_init failed", __func__);
|
||||
return false;
|
||||
}
|
||||
data->handle.data = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean send_name_owner_request(struct service_data* data, const char* name)
|
||||
{
|
||||
DBusMessage* msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
|
||||
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetNameOwner");
|
||||
if (!msg) {
|
||||
error("%s: dbus_message_new_method_call failed", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
|
||||
if (!dbus_connection_send_with_reply(data->conn, msg, &data->call, -1)) {
|
||||
error("%s: dbus_connection_send_with_reply failed", __func__);
|
||||
dbus_message_unref(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!data->call) {
|
||||
error("%s: dbus reply failed with empty pendingcall", __func__);
|
||||
dbus_message_unref(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dbus_pending_call_get_completed(data->call)) {
|
||||
service_reply(data->call, data);
|
||||
} else {
|
||||
dbus_pending_call_set_notify(data->call, service_reply, data, NULL);
|
||||
}
|
||||
|
||||
dbus_message_unref(msg);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void check_service(DBusConnection* conn, const char* name,
|
||||
struct filter_callback* cb, DBusList* listener_list)
|
||||
{
|
||||
struct service_data* data = create_service_data(conn, name, cb);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (!init_uv_handle(data)) {
|
||||
dbus_connection_unref(data->conn);
|
||||
free(data->name);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
data->owner = check_name_cache(listener_list, name);
|
||||
if (data->owner) {
|
||||
if (uv_idle_start(&data->handle, update_service) != 0) {
|
||||
error("%s: uv_idle_start failed:", __func__);
|
||||
uv_close((uv_handle_t*)&data->handle, NULL);
|
||||
dbus_connection_unref(data->conn);
|
||||
free(data->name);
|
||||
free(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (send_name_owner_request(data, name) == FALSE) {
|
||||
uv_close((uv_handle_t*)&data->handle, NULL);
|
||||
dbus_connection_unref(data->conn);
|
||||
free(data->name);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
guint dbus_add_service_watch(GDBusWatch* watcher, const char* name,
|
||||
GDBusWatchFunction connect,
|
||||
GDBusWatchFunction disconnect,
|
||||
void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
struct filter_data* data;
|
||||
struct filter_callback* cb;
|
||||
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
|
||||
data = filter_data_get(watcher, service_filter, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
|
||||
DBUS_INTERFACE_DBUS, "NameOwnerChanged", name);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
|
||||
cb = filter_data_add_callback(data, connect, disconnect, NULL, destroy,
|
||||
get_watch_serial(watcher), user_data);
|
||||
if (cb == NULL)
|
||||
return 0;
|
||||
|
||||
if (connect)
|
||||
check_service(watcher->conn, name, cb, watcher->list);
|
||||
|
||||
return cb->id;
|
||||
}
|
||||
|
||||
guint dbus_add_service_disconnect_watch(GDBusWatch* watcher, const char* name,
|
||||
GDBusWatchFunction func, void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
return dbus_add_service_watch(watcher, name, NULL, func, user_data, destroy);
|
||||
}
|
||||
|
||||
guint dbus_add_signal_watch(GDBusWatch* watcher,
|
||||
const char* sender, const char* path,
|
||||
const char* interface, const char* member,
|
||||
GDBusSignalFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy)
|
||||
{
|
||||
struct filter_data* data;
|
||||
struct filter_callback* cb;
|
||||
|
||||
data = filter_data_get(watcher, signal_filter, sender, path,
|
||||
interface, member, NULL);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
|
||||
cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
|
||||
get_watch_serial(watcher), user_data);
|
||||
if (cb == NULL)
|
||||
return 0;
|
||||
|
||||
if (data->name != NULL && data->name_watch == 0)
|
||||
data->name_watch = dbus_add_service_watch(watcher,
|
||||
data->name, NULL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
return cb->id;
|
||||
}
|
||||
|
||||
guint dbus_add_properties_watch(GDBusWatch* watcher,
|
||||
const char* sender, const char* path,
|
||||
const char* interface,
|
||||
GDBusSignalFunction function, void* user_data,
|
||||
GDBusDestroyFunction destroy)
|
||||
{
|
||||
struct filter_data* data;
|
||||
struct filter_callback* cb;
|
||||
|
||||
data = filter_data_get(watcher, signal_filter, sender, path,
|
||||
DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", interface);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
|
||||
cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
|
||||
get_watch_serial(watcher), user_data);
|
||||
if (cb == NULL)
|
||||
return 0;
|
||||
|
||||
if (data->name != NULL && data->name_watch == 0)
|
||||
data->name_watch = dbus_add_service_watch(watcher,
|
||||
data->name, NULL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
return cb->id;
|
||||
}
|
||||
|
||||
gboolean dbus_remove_watch(GDBusWatch* watcher, guint id)
|
||||
{
|
||||
struct filter_data* data;
|
||||
struct filter_callback* cb;
|
||||
DBusList* ldata;
|
||||
|
||||
if (id == 0)
|
||||
return FALSE;
|
||||
|
||||
for (ldata = _dbus_list_get_first_link(&watcher->list); ldata != NULL;
|
||||
ldata = _dbus_list_get_next_link(&watcher->list, ldata)) {
|
||||
data = ldata->data;
|
||||
|
||||
cb = filter_data_find_callback(data, id);
|
||||
if (cb) {
|
||||
filter_data_remove_callback(data, cb);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void dbus_remove_all_watches(GDBusWatch* watcher)
|
||||
{
|
||||
struct filter_data* data;
|
||||
|
||||
while ((data = filter_data_find(watcher->conn, watcher->list))) {
|
||||
_dbus_list_remove(&watcher->list, data);
|
||||
filter_data_call_and_free(data, watcher->list);
|
||||
}
|
||||
}
|
||||
|
||||
GDBusWatch* new_dbus_watch(DBusConnection* connection)
|
||||
{
|
||||
GDBusWatch* watcher;
|
||||
|
||||
watcher = calloc(1, sizeof(GDBusWatch));
|
||||
if (watcher == NULL)
|
||||
return NULL;
|
||||
|
||||
watcher->conn = dbus_connection_ref(connection);
|
||||
watcher->list = NULL;
|
||||
watcher->serial = 0;
|
||||
watcher->conn_closed = FALSE;
|
||||
|
||||
return watcher;
|
||||
}
|
||||
void free_dbus_watch(GDBusWatch* watcher)
|
||||
{
|
||||
dbus_connection_unref(watcher->conn);
|
||||
free(watcher);
|
||||
}
|
||||
|
||||
guint dbus_client_add_service_watch(GDBusClient* client, const char* name,
|
||||
GDBusWatchFunction connect, GDBusWatchFunction disconnect,
|
||||
void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
return dbus_add_service_watch(client->watcher, name, connect, disconnect,
|
||||
user_data, destroy);
|
||||
}
|
||||
|
||||
guint dbus_client_add_service_disconnect_watch(GDBusClient* client, const char* name,
|
||||
GDBusWatchFunction function, void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
return dbus_add_service_disconnect_watch(client->watcher, name, function, user_data, destroy);
|
||||
}
|
||||
|
||||
guint dbus_client_add_signal_watch(GDBusClient* client, const char* sender,
|
||||
const char* path, const char* interface, const char* member,
|
||||
GDBusSignalFunction function, void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
return dbus_add_signal_watch(client->watcher, sender, path, interface,
|
||||
member, function, user_data, destroy);
|
||||
}
|
||||
|
||||
guint dbus_client_add_properties_watch(GDBusClient* client,
|
||||
const char* sender, const char* path, const char* interface,
|
||||
GDBusSignalFunction function, void* user_data, GDBusDestroyFunction destroy)
|
||||
{
|
||||
return dbus_add_properties_watch(client->watcher, sender, path, interface,
|
||||
function, user_data, destroy);
|
||||
}
|
||||
|
||||
gboolean dbus_client_remove_watch(GDBusClient* client, guint tag)
|
||||
{
|
||||
return dbus_remove_watch(client->watcher, tag);
|
||||
}
|
||||
|
||||
void dbus_client_remove_all_watches(GDBusClient* client)
|
||||
{
|
||||
dbus_remove_all_watches(client->watcher);
|
||||
}
|
||||
|
||||
void dbus_watch_set_connection_state(GDBusWatch* watcher, gboolean closed)
|
||||
{
|
||||
watcher->conn_closed = closed;
|
||||
}
|
||||
123
kvdb/client.c
123
kvdb/client.c
|
|
@ -67,77 +67,13 @@ static ssize_t recv_safe(int sockfd, char* buf, size_t offset, size_t len)
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: property_connect_one
|
||||
* Name: property_connect
|
||||
*
|
||||
* Description:
|
||||
* Initialize client socket and connect to server
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - server address
|
||||
* addrlen - server address length
|
||||
*
|
||||
* Returned Value:
|
||||
* On success return client socket fd.
|
||||
* On error return error value (<0).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_RPMSG)
|
||||
static int property_connect_one(const struct sockaddr* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
int fd = socket(addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
int ret = connect(fd, addr, addrlen);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_LOCAL) && defined(CONFIG_NET_RPMSG)
|
||||
/****************************************************************************
|
||||
* Name: use_local_socket
|
||||
*
|
||||
* Description:
|
||||
* Determine whether to use local socket or rpmsg socket to
|
||||
* connect to server
|
||||
*
|
||||
* Returned Value:
|
||||
* true: use local socket
|
||||
* false: use rpmsg socket
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool use_local_socket(void)
|
||||
{
|
||||
#ifdef CONFIG_KVDB_SERVER_CPUNAME
|
||||
struct sockaddr_rpmsg addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int fd = socket(AF_RPMSG, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (fd >= 0) {
|
||||
int ret = getsockname(fd, (struct sockaddr*)&addr, &addrlen);
|
||||
close(fd);
|
||||
if (ret == 0) {
|
||||
return strcmp(addr.rp_cpu, CONFIG_KVDB_SERVER_CPUNAME) == 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: property_connect
|
||||
*
|
||||
* Description:
|
||||
* Initialize client socket and connect to server
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success return client socket fd.
|
||||
|
|
@ -147,45 +83,48 @@ static inline bool use_local_socket(void)
|
|||
|
||||
static int property_connect(void)
|
||||
{
|
||||
#ifdef CONFIG_NET_LOCAL
|
||||
const struct sockaddr_un laddr = {
|
||||
#ifdef CONFIG_KVDB_SERVER
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
#else
|
||||
int fd = socket(AF_RPMSG, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
#if CONFIG_KVDB_TIMEOUT_INTERVAL
|
||||
struct timeval timeout = {
|
||||
.tv_sec = CONFIG_KVDB_TIMEOUT_INTERVAL,
|
||||
.tv_usec = 0,
|
||||
};
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KVDB_SERVER
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = PROP_SERVER_PATH,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_RPMSG
|
||||
const struct sockaddr_rpmsg raddr = {
|
||||
#else
|
||||
struct sockaddr_rpmsg addr = {
|
||||
.rp_family = AF_RPMSG,
|
||||
.rp_name = PROP_SERVER_PATH,
|
||||
.rp_cpu = CONFIG_KVDB_SERVER_CPUNAME,
|
||||
};
|
||||
#endif
|
||||
int ret = -ENOTSUP;
|
||||
#if defined(CONFIG_NET_LOCAL) && defined(CONFIG_NET_RPMSG)
|
||||
bool use_local = use_local_socket();
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
#if defined(CONFIG_NET_LOCAL) && defined(CONFIG_NET_RPMSG)
|
||||
if (use_local)
|
||||
ret = property_connect_one((const struct sockaddr*)&laddr, sizeof(laddr));
|
||||
else
|
||||
ret = property_connect_one((const struct sockaddr*)&raddr, sizeof(raddr));
|
||||
#elif defined(CONFIG_NET_LOCAL)
|
||||
ret = property_connect_one((const struct sockaddr*)&laddr, sizeof(laddr));
|
||||
#elif defined(CONFIG_NET_RPMSG)
|
||||
ret = property_connect_one((const struct sockaddr*)&raddr, sizeof(raddr));
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
break;
|
||||
int ret = connect(fd, (const struct sockaddr*)&addr, sizeof(addr));
|
||||
if (ret < 0 && errno != ENOENT) {
|
||||
ret = -errno;
|
||||
close(fd);
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ static int kvdb_monitor_open(kvdb_server* server, int fd, const char* key,
|
|||
/* Malloc monitor element to store [key, fd] pair */
|
||||
kvdb_monitor* mon = zalloc(sizeof(kvdb_monitor) + key_len);
|
||||
if (mon == NULL) {
|
||||
KVERR("kvdb_monitor_open: zalloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +78,6 @@ static int kvdb_monitor_open(kvdb_server* server, int fd, const char* key,
|
|||
};
|
||||
int ret = epoll_ctl(server->efd, EPOLL_CTL_ADD, fd, &ev);
|
||||
if (ret < 0) {
|
||||
KVERR("kvdb_monitor_open: epoll_ctl failed, ret=%d, errno=%d\n", ret, errno);
|
||||
free(mon);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -291,22 +289,16 @@ static int kvdb_bind(int fd[])
|
|||
|
||||
for (int i = 0; i < KVFD_COUNT; i++) {
|
||||
fd[i] = socket(family[i], SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (fd[i] < 0) {
|
||||
KVERR("kvdb_bind: socket failed, i=%d, errno=%d\n", i, errno);
|
||||
if (fd[i] < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
int ret = bind(fd[i], addr[i], addrlen[i]);
|
||||
if (ret < 0) {
|
||||
KVERR("kvdb_bind: bind failed, i=%d, ret=%d, errno=%d\n", i, ret, errno);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = listen(fd[i], CONFIG_KVDB_BACKLOG_CONNS);
|
||||
if (ret < 0) {
|
||||
KVERR("kvdb_bind: listen failed, i=%d, ret=%d, errno=%d\n", i, ret, errno);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -346,14 +338,10 @@ static ssize_t kvdb_recv(int sockfd, char* buf, size_t offset, size_t len)
|
|||
{
|
||||
while (offset < len) {
|
||||
ssize_t ret = recv(sockfd, buf + offset, len - offset, 0);
|
||||
if (ret < 0) {
|
||||
KVERR("kvdb_recv: recv failed, ret=%zd, errno=%d\n", ret, errno);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) {
|
||||
KVERR("kvdb_recv: recv returned 0, connection closed\n");
|
||||
if (ret == 0)
|
||||
return -ENODATA;
|
||||
}
|
||||
offset += ret;
|
||||
}
|
||||
|
||||
|
|
@ -366,30 +354,26 @@ static bool kvdb_client(kvdb_server* server, int fd)
|
|||
ssize_t len;
|
||||
char* msg;
|
||||
|
||||
#if defined(CONFIG_KVDB_TIMEOUT_INTERVAL) && CONFIG_KVDB_TIMEOUT_INTERVAL > 0
|
||||
#if CONFIG_KVDB_TIMEOUT_INTERVAL
|
||||
struct timeval timeout = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = CONFIG_KVDB_TIMEOUT_INTERVAL,
|
||||
.tv_sec = CONFIG_KVDB_TIMEOUT_INTERVAL,
|
||||
.tv_usec = 0,
|
||||
};
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0
|
||||
|| setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
|
||||
KVWARN("Failed to set socket timeout\n");
|
||||
}
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
#endif
|
||||
|
||||
msg = malloc(PROP_MSG_MAX);
|
||||
if (msg == NULL) {
|
||||
KVERR("kvdb_client: malloc failed\n");
|
||||
KVERR("malloc failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg[0] = msg[1] = msg[2] = 0; /* zero the first key bytes */
|
||||
|
||||
len = recv(fd, msg, PROP_MSG_MAX, 0);
|
||||
if (len <= 0) {
|
||||
KVERR("kvdb_client: recv failed, len=%zd, errno=%d\n", len, errno);
|
||||
if (len <= 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (msg[0]) {
|
||||
case 'D': {
|
||||
|
|
@ -522,7 +506,6 @@ static bool kvdb_client(kvdb_server* server, int fd)
|
|||
}
|
||||
case 'E': {
|
||||
int ret = 0;
|
||||
KVERR("kvdb_client: received exit command, stopping server\n");
|
||||
server->running = false;
|
||||
kvdb_uninit(server->kvdb);
|
||||
send(fd, &ret, sizeof(ret), 0);
|
||||
|
|
@ -542,17 +525,14 @@ static void kvdb_loop(kvdb_server* server)
|
|||
struct timespec ts;
|
||||
|
||||
server->efd = epoll_create(KVFD_MAX);
|
||||
if (server->efd < 0) {
|
||||
KVERR("kvdb_loop: epoll_create failed, errno=%d\n", errno);
|
||||
if (server->efd < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < KVFD_COUNT; i++) {
|
||||
if (server->fd[i] >= 0) {
|
||||
evs[0].data.ptr = &server->fd[i];
|
||||
evs[0].events = EPOLLIN;
|
||||
if (epoll_ctl(server->efd, EPOLL_CTL_ADD, server->fd[i], &evs[0]) < 0) {
|
||||
KVERR("kvdb_loop: epoll_ctl ADD failed, fd=%d, errno=%d\n", server->fd[i], errno);
|
||||
close(server->efd);
|
||||
return;
|
||||
}
|
||||
|
|
@ -606,7 +586,6 @@ static void kvdb_loop(kvdb_server* server)
|
|||
}
|
||||
}
|
||||
}
|
||||
KVERR("kvdb_loop: server loop exited, running=%d\n", server->running);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -630,21 +609,16 @@ int main(int argc, char* argv[])
|
|||
.head = LIST_HEAD_INITIALIZER(),
|
||||
};
|
||||
int ret = kvdb_bind(server.fd);
|
||||
if (ret < 0) {
|
||||
KVERR("main: kvdb_bind failed, ret=%d, errno=%d\n", ret, errno);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = kvdb_init(&server.kvdb);
|
||||
if (ret < 0) {
|
||||
KVERR("main: kvdb_init failed, ret=%d\n", ret);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
kvdb_load(server.kvdb, CONFIG_KVDB_SOURCE_PATH, false);
|
||||
kvdb_loop(&server);
|
||||
out:
|
||||
KVERR("main: exiting, ret=%d\n", ret);
|
||||
kvdb_unbind(server.fd);
|
||||
return -ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,58 +55,58 @@ void atrace_set_tracing_enabled(bool enabled)
|
|||
|
||||
void atrace_begin_body(const char* name)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "B|%d|%s", gettid(), name);
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "B|%d|%s", gettid(), name);
|
||||
}
|
||||
|
||||
void atrace_end_body(void)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "E|%d", gettid());
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "E|%d", gettid());
|
||||
}
|
||||
|
||||
void atrace_async_begin_body(const char* name, int32_t cookie)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "S|%d|%s|%" PRId32, gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "S|%d|%s|%" PRId32, gettid(),
|
||||
name, cookie);
|
||||
}
|
||||
|
||||
void atrace_async_end_body(const char* name, int32_t cookie)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "F|%d|%s|%" PRId32, gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "F|%d|%s|%" PRId32, gettid(),
|
||||
name, cookie);
|
||||
}
|
||||
|
||||
void atrace_async_for_track_begin_body(const char* track_name,
|
||||
const char* name, int32_t cookie)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "G|%d|%s|%s|%" PRId32, gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "G|%d|%s|%s|%" PRId32, gettid(),
|
||||
track_name, name, cookie);
|
||||
}
|
||||
|
||||
void atrace_async_for_track_end_body(const char* track_name, const char* name, int32_t cookie)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "H|%d|%s|%s|%" PRId32, gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "H|%d|%s|%s|%" PRId32, gettid(),
|
||||
track_name, name, cookie);
|
||||
}
|
||||
|
||||
void atrace_instant_body(const char* name)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "I|%d|%s", gettid(), name);
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "I|%d|%s", gettid(), name);
|
||||
}
|
||||
|
||||
void atrace_instant_for_track_body(const char* track_name, const char* name)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "N|%d|%s|%s", gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "N|%d|%s|%s", gettid(),
|
||||
track_name, name);
|
||||
}
|
||||
|
||||
void atrace_int_body(const char* name, int32_t value)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "C|%d|%s|%" PRId32,
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "C|%d|%s|%" PRId32,
|
||||
gettid(), name, value);
|
||||
}
|
||||
|
||||
void atrace_int64_body(const char* name, int64_t value)
|
||||
{
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, LOG_INFO, "C|%d|%s|%" PRId64, gettid(),
|
||||
sched_note_printf(NOTE_TAG_ALWAYS, "C|%d|%s|%" PRId64, gettid(),
|
||||
name, value);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue