From 8f64868f9edd313eaee9a73abc3f79110da5f132 Mon Sep 17 00:00:00 2001 From: Raquel Medina Date: Fri, 15 Feb 2019 17:10:40 +0200 Subject: binding: identity: fix segfault & update to v3 forgerock binding calls On user login via nfc, the identity service segfaults on nfc event processing. Fix segfault, update forgerock compilation unit to use binding V3 call methods and review the identity agent baseline to remove unused code / tidy up. Bug-AGL: SPEC-2158 Change-Id: Ic87e630e9d028ba22937468375631b8e908011f8 Signed-off-by: Raquel Medina --- src/agl-forgerock.c | 105 ++++++++++--------- src/agl-identity-binding.c | 245 +++++++++++++++++++++++++++------------------ src/agl-identity-common.h | 28 ++++++ src/aia-get.c | 20 ---- src/curl-wrap.c | 6 +- src/curl-wrap.h | 3 - src/test-aia-uds-bluez.c | 65 ------------ 7 files changed, 239 insertions(+), 233 deletions(-) create mode 100644 src/agl-identity-common.h delete mode 100644 src/test-aia-uds-bluez.c (limited to 'src') diff --git a/src/agl-forgerock.c b/src/agl-forgerock.c index 97cc4b9..90c2e8f 100644 --- a/src/agl-forgerock.c +++ b/src/agl-forgerock.c @@ -21,34 +21,36 @@ #include -#define AFB_BINDING_VERSION 2 +#define AFB_BINDING_VERSION 3 #include +#include "agl-identity-common.h" #include "oidc-agent.h" #include "aia-get.h" -#ifndef NULL -#define NULL 0 -#endif - static int expiration_delay = 5; -static const char default_endpoint[] = "https://agl-graphapi.forgerocklabs.org/getuserprofilefromtoken"; +static const char default_endpoint[] = + "https://agl-graphapi.forgerocklabs.org/getuserprofilefromtoken"; + static const char *oidc_name; static char *endpoint; static void (*onloaded)(struct json_object *data, const char *error); + /***** configuration ********************************************/ -static void confsetstr(struct json_object *conf, const char *name, char **value, const char *def) +static void confsetstr(struct json_object *conf, + const char *name, char **value, const char *def) { struct json_object *v; const char *s; char *p; - s = conf && json_object_object_get_ex(conf, name, &v) ? json_object_get_string(v) : def; + s = conf && json_object_object_get_ex(conf, name, &v) ? + json_object_get_string(v) : def; p = *value; if (s && p != s) { *value = strdup(s); @@ -56,24 +58,27 @@ static void confsetstr(struct json_object *conf, const char *name, char **value, } } -static void confsetint(struct json_object *conf, const char *name, int *value, int def) +static void confsetint(struct json_object *conf, + const char *name, int *value, int def) { struct json_object *v; - *value = conf && json_object_object_get_ex(conf, name, &v) ? json_object_get_int(v) : def; + *value = conf && json_object_object_get_ex(conf, name, &v) ? + json_object_get_int(v) : def; } static void confsetoidc(struct json_object *conf, const char *name) { struct json_object *idp, *appli; - if (conf - && json_object_object_get_ex(conf, "idp", &idp) - && json_object_object_get_ex(conf, "appli", &appli)) { - if (oidc_idp_set(name, idp) && oidc_appli_set(name, name, appli, 1)) { + if (!conf || + !json_object_object_get_ex(conf, "idp", &idp) || + !json_object_object_get_ex(conf, "appli", &appli)) + return; + + if (oidc_idp_set(name, idp) && + oidc_appli_set(name, name, appli, 1)) oidc_name = name; - } - } } /****************************************************************/ @@ -84,7 +89,8 @@ static void loaded(struct json_object *data, const char *error) onloaded(data, error); } -static void downloaded(void *closure, int status, const void *buffer, size_t size) +static void downloaded(void *closure, int status, + const void *buffer, size_t size) { struct json_object *object, *subobj; struct json_object *objkey = closure; @@ -97,14 +103,15 @@ static void downloaded(void *closure, int status, const void *buffer, size_t siz if (status == 0 && !buffer) { AFB_ERROR("discarded"); loaded(NULL, "discarded"); - goto end; /* discarded */ + goto ignore; } /* scan for the status */ if (status == 0 || !buffer) { - AFB_ERROR("uploading %s failed %s", url ? : "?", (const char*)buffer ? : ""); + AFB_ERROR("uploading %s failed %s", url ? : "?", + (const char*)buffer ? : ""); loaded(NULL, "failed"); - goto end; + goto ignore; } /* get the object */ @@ -132,7 +139,7 @@ static void downloaded(void *closure, int status, const void *buffer, size_t siz AFB_INFO("unrecognized key for %s", url ? : "?"); json_object_put(object); loaded(NULL, "malformed"); - goto end; + goto ignore; } // Save the profile to the database @@ -140,11 +147,14 @@ static void downloaded(void *closure, int status, const void *buffer, size_t siz struct json_object* record = json_object_new_object(); json_object_object_add(record, "key", objkey); json_object_object_add(record, "value", json_object_get(subobj)); - afb_service_call_sync("persistence", "update", record, &dbr); + afb_api_call_sync(get_local_api(), "persistence", "update", + record, &dbr, NULL, NULL); loaded(subobj, NULL); json_object_put(object); -end: + json_object_put(dbr); + + ignore: json_object_put(objkey); } @@ -158,7 +168,8 @@ void agl_forgerock_setconfig(struct json_object *conf) AFB_NOTICE("Forgerock endpoint is: %s", endpoint); } -void agl_forgerock_setcb(void (*callback)(struct json_object *data, const char *error)) +void agl_forgerock_setcb( + void (*callback)(struct json_object *data, const char *error)) { onloaded = callback; } @@ -174,35 +185,39 @@ void reply_from_db(void* closure, int status, struct json_object* result) struct json_object* tmp; json_object_object_get_ex(result, "response", &tmp); json_object_object_get_ex(tmp, "value", &tmp); - AFB_NOTICE("User profile retrieved from persistence: %s", json_object_to_json_string(tmp)); + AFB_NOTICE("User profile retrieved from persistence: %s", + json_object_to_json_string(tmp)); loaded(json_object_get(tmp), NULL); } -void agl_forgerock_download_request(const char *vin, const char *kind, const char *key) +void agl_forgerock_download_request(const char *vin, + const char *kind, + const char *key) { int rc; char *url; - rc = asprintf(&url, "%s?vin=%s&kind=%s&keytoken=%s", endpoint, vin, kind, key); - if (rc >= 0) - { - struct json_object* obj = json_object_new_object(); - json_object_object_add(obj, "url", json_object_new_string(url)); - json_object_object_add(obj, "vin", json_object_new_string(vin)); - json_object_object_add(obj, "kind", json_object_new_string(kind)); - json_object_object_add(obj, "key", json_object_new_string(key)); - - // Async get from database and from forgerock - struct json_object* key = json_object_new_object(); - json_object_object_add(key, "key", json_object_get(obj)); - afb_service_call("persistence", "read", key, reply_from_db, NULL); - - // Async get from forgerock - aia_get(url, expiration_delay, oidc_name, oidc_name, downloaded, obj); - free(url); - } - else + rc = asprintf(&url, "%s?vin=%s&kind=%s&keytoken=%s", + endpoint, vin, kind, key); + if (rc < 0) { AFB_ERROR("out of memory"); + return; + } + + struct json_object* obj = json_object_new_object(); + json_object_object_add(obj, "url", json_object_new_string(url)); + json_object_object_add(obj, "vin", json_object_new_string(vin)); + json_object_object_add(obj, "kind", json_object_new_string(kind)); + json_object_object_add(obj, "key", json_object_new_string(key)); + + // Async get from database and from forgerock + struct json_object* key_obj = json_object_new_object(); + json_object_object_add(key_obj, "key", json_object_get(obj)); + afb_api_call(get_local_api(), "persistence", "read", key_obj, reply_from_db, NULL); + + // Async get from forgerock + aia_get(url, expiration_delay, oidc_name, oidc_name, downloaded, obj); + free(url); } /* vim: set colorcolumn=80: */ diff --git a/src/agl-identity-binding.c b/src/agl-identity-binding.c index 70c195c..f246ea9 100644 --- a/src/agl-identity-binding.c +++ b/src/agl-identity-binding.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -29,15 +30,21 @@ #include "agl-forgerock.h" +static afb_api_t this_api; static afb_event_t event; + static json_object *current_identity; /* default vin corresponds to Toyota Camry 2016, 429 */ static const char default_vin[] = "4T1BF1FK5GU260429"; static char *vin; -/***** configuration ********************************************/ +afb_api_t get_local_api(void) +{ + return this_api; +} +/***** configuration from file **********************************/ static struct json_object *readjson(int fd) { char *buffer; @@ -50,12 +57,7 @@ static struct json_object *readjson(int fd) buffer = alloca((size_t)(s.st_size)+1); if (read(fd, buffer, (size_t)s.st_size) == (ssize_t)s.st_size) { buffer[s.st_size] = 0; - //AFB_API_NOTICE(afbBindingV3root, "Config file: %s", buffer); result = json_tokener_parse(buffer); - //if (!result) - //{ - // AFB_API_ERROR(afbBindingV3root, "Config file is not a valid JSON: %s", json_tokener_error_desc(json_tokener_get_error(NULL))); - //} } } close(fd); @@ -66,7 +68,7 @@ static struct json_object *readjson(int fd) static struct json_object *get_global_config(const char *name, const char *locale) { int fd = afb_daemon_rootdir_open_locale(name, O_RDONLY, locale); - if (fd < 0) AFB_API_ERROR(afbBindingV3root, "Config file not found: %s", name); + if (fd < 0) AFB_API_ERROR(this_api, "Config file not found: %s", name); return fd < 0 ? NULL : readjson(fd); } @@ -83,7 +85,8 @@ static void confsetstr(struct json_object *conf, const char *name, const char *s; char *p; - s = conf && json_object_object_get_ex(conf, name, &v) ? json_object_get_string(v) : def; + s = conf && json_object_object_get_ex(conf, name, &v) ? + json_object_get_string(v) : def; p = *value; if (s && p != s) { *value = strdup(s); @@ -108,11 +111,16 @@ static void readconfig() /****************************************************************/ -static struct json_object *make_event_object(const char *name, const char *id, const char *nick) +static struct json_object *make_event_object(const char *name, + const char *id, + const char *nick) { - struct json_object *object = json_object_new_object(); + struct json_object *object; - /* TODO: errors */ + if (!name || !id ) + return NULL; + + object = json_object_new_object(); json_object_object_add(object, "eventName", json_object_new_string(name)); json_object_object_add(object, "accountid", json_object_new_string(id)); if (nick) @@ -127,39 +135,44 @@ static int send_event_object(const char *name, const char *id, const char *nick) static void do_login(struct json_object *desc) { - if (current_identity == NULL && desc == NULL) return; // Switching from NULL to NULL -> do nothing + /* if switching from NULL to NULL -> do nothing */ + if (current_identity == NULL && desc == NULL) return; + + /* if switching from one user to the same user -> do nothing */ if (current_identity && desc) { const char* a = json_object_to_json_string(current_identity); const char* b = json_object_to_json_string(desc); if (strcmp(a, b) == 0) { - AFB_API_NOTICE(afbBindingV3root, "Reloging of the same user."); - return; // Switching from one user to the same user -> do nothing + AFB_API_NOTICE(this_api, "re-logging the same user!"); + return; } } struct json_object *object; - /* switching the user */ - AFB_API_INFO(afbBindingV3root, "Switching to user %s", + /* switching to a different user */ + AFB_API_INFO(this_api, "Switching to user %s", desc ? json_object_to_json_string(desc) : "null"); object = current_identity; current_identity = json_object_get(desc); json_object_put(object); if (!json_object_object_get_ex(desc, "name", &object)) - object = 0; - send_event_object("login", !object ? "null" : json_object_get_string(object)? : "?", 0); + object = NULL; + send_event_object("login", + !object ? "null" : json_object_get_string(object)? : "?", + 0); } static void do_logout() { struct json_object *object; - AFB_API_INFO(afbBindingV3root, "Switching to no user"); + AFB_API_INFO(this_api, "Switching to no user"); object = current_identity; - current_identity = 0; + current_identity = NULL; json_object_put(object); send_event_object("logout", "null", 0); @@ -168,50 +181,12 @@ static void do_logout() static void on_forgerock_data(struct json_object *data, const char *error) { if (error) { - AFB_API_ERROR(afbBindingV3root, "Can't get data: %s", error); + AFB_API_ERROR(this_api, "Can't get data: %s", error); } else { do_login(data); } } -/****************************************************************/ - -static void subscribe (afb_req_t request) -{ - if (afb_req_subscribe(request, event)) { - AFB_REQ_ERROR(request, "subscribe error"); - afb_req_reply(request, NULL, "failed", "subscribtion failed"); - } - else - afb_req_reply(request, NULL, NULL, NULL); -} - -static void unsubscribe (afb_req_t request) -{ - afb_req_unsubscribe(request, event); - afb_req_reply(request, NULL, NULL, NULL); -} - -static void logout (afb_req_t request) -{ - do_logout(); - afb_req_reply(request, NULL, NULL, NULL); -} - -static void fake_login (afb_req_t request) -{ - struct json_object *desc = afb_req_json(request); - do_logout(); - if (desc) - do_login(desc); - afb_req_reply(request, NULL, NULL, NULL); -} - -static void get (afb_req_t request) -{ - afb_req_reply(request, json_object_get(current_identity), NULL, NULL); -} - static void on_nfc_subscribed(void *closure, struct json_object *result, const char *error, const char *info, afb_api_t api) @@ -225,48 +200,77 @@ static void on_nfc_subscribed(void *closure, struct json_object *result, static int service_init(afb_api_t api) { struct json_object *jrequest = NULL; + int ret; - agl_forgerock_setcb(on_forgerock_data); + this_api = api; - event = afb_api_make_event(api, "event"); - if (!afb_event_is_valid(event)) { - AFB_API_ERROR(api, "Failed to create event"); - return -1; + ret = afb_api_require_api(this_api, "nfc", 1); + if (ret < 0) { + AFB_API_ERROR(this_api, "nfc api not available"); + goto out; } - - readconfig(); - if (afb_api_require_api(api, "nfc", 1)) - return -1; + ret = afb_api_require_api(this_api, "persistence", 1); + if (ret < 0) { + AFB_API_ERROR(this_api, "persistence api not available"); + goto out; + } - if (afb_api_require_api(api, "persistence", 1)) - return -1; + event = afb_api_make_event(this_api, "event"); + if (!afb_event_is_valid(event)) { + AFB_API_ERROR(this_api, "Failed to create event"); + ret = -EINVAL; + goto out; + } + + readconfig(); + agl_forgerock_setcb(on_forgerock_data); jrequest = json_object_new_object(); json_object_object_add(jrequest, "value", json_object_new_string("presence")); - afb_api_call(api, "nfc", "subscribe", jrequest, on_nfc_subscribed, NULL); - return 0; +out: + return ret; } static void on_nfc_target_add(struct json_object *object) { - struct json_object * json_uid; + struct json_object *json_status; + struct json_object *json_uid; const char *uid; + + if (!object) { + AFB_API_ERROR(this_api, "nfc/presence empty args"); + goto out; + } + + if (!json_object_object_get_ex(object, "status", &json_status)) { + AFB_API_ERROR(this_api, "nfc/presence missing status"); + goto out; + } + + if (strncmp(json_object_get_string(json_status), "detected", 8)) { + AFB_API_WARNING(this_api, "Not a tag detected event!"); + goto out; + } + if (json_object_object_get_ex(object, "uid", &json_uid)) { uid = json_object_get_string(json_uid); - AFB_API_NOTICE(afbBindingV3root, + AFB_API_NOTICE(this_api, "nfc tag detected, call forgerock with vincode=%s and key=%s", vin ? vin : default_vin, uid); - send_event_object("incoming", uid, uid); + agl_forgerock_download_request(vin ? vin : default_vin, "nfc", uid); } - else AFB_API_ERROR(afbBindingV3root, - "nfc target add event is received but no UID found: %s", - json_object_to_json_string(object)); + else + AFB_API_ERROR(this_api, + "nfc tag detected event but no UID found: %s", + json_object_to_json_string(object)); +out: + return; } static void onevent(afb_api_t api, const char *event, struct json_object *object) @@ -277,9 +281,61 @@ static void onevent(afb_api_t api, const char *event, struct json_object *object on_nfc_target_add(object); return; } + AFB_API_WARNING(api, "Unhandled event: %s", event); } +/****************************************************************/ + +static void subscribe (afb_req_t request) +{ + if (afb_req_subscribe(request, event)) { + AFB_REQ_ERROR(request, "subscribe to identity event failed"); + afb_req_reply(request, NULL, "failed", "subscribe error"); + return; + } + + afb_req_reply(request, NULL, NULL, NULL); +} + +static void unsubscribe (afb_req_t request) +{ + if (afb_req_unsubscribe(request, event)) { + AFB_REQ_ERROR(request, "unsubscribe to identity event failed"); + afb_req_reply(request, NULL, "failed", "unsubscribe error"); + return; + } + + afb_req_reply(request, NULL, NULL, NULL); +} + +static void logout (afb_req_t request) +{ + do_logout(); + afb_req_reply(request, NULL, NULL, NULL); +} + +/* + * verb "fake_login" intended for testing: force sending a login event + */ +static void fake_login (afb_req_t request) +{ + struct json_object *desc = afb_req_json(request); + do_logout(); + if (desc) + do_login(desc); + afb_req_reply(request, NULL, NULL, NULL); +} + +static void get (afb_req_t request) +{ + afb_req_reply(request, json_object_get(current_identity), NULL, NULL); +} + +/* + * verb "fake_auth" intended for testing: trigger authentication on the + * provided data (e.g same args as per the "nfc/presence" event) + */ static void fake_auth(afb_req_t req) { struct json_object* req_object; @@ -294,18 +350,15 @@ static void fake_auth(afb_req_t req) AFB_REQ_ERROR(req, "bad request: %s", json_object_get_string(req_object)); afb_req_reply(req, NULL, "Missing arg", NULL); + return; } - else { - const char* kind = json_object_get_string(kind_object); - const char* key = json_object_get_string(key_object); - AFB_REQ_NOTICE(req, "kind: %s, key: %s", kind, key); - - send_event_object("incoming", key, key); - agl_forgerock_download_request(vin ? vin : default_vin, kind, key); + const char* kind = json_object_get_string(kind_object); + const char* key = json_object_get_string(key_object); - afb_req_reply(req, NULL, NULL, "fake auth success!"); - } + AFB_REQ_NOTICE(req, "kind: %s, key: %s", kind, key); + agl_forgerock_download_request(vin ? vin : default_vin, kind, key); + afb_req_reply(req, NULL, NULL, "fake auth success!"); } /* @@ -314,31 +367,29 @@ static void fake_auth(afb_req_t req) */ const afb_verb_t verbs[]= { - {.verb = "subscribe" , .callback = subscribe , .auth = NULL, + {.verb = "subscribe" , .callback = subscribe , .info = "subscribe to events" , .session = AFB_SESSION_NONE }, - {.verb = "unsubscribe", .callback = unsubscribe , .auth = NULL, + {.verb = "unsubscribe", .callback = unsubscribe , .info = "unsubscribe to events" , .session = AFB_SESSION_NONE }, - {.verb = "fake-login" , .callback = fake_login , .auth = NULL, + {.verb = "fake-login" , .callback = fake_login , .info = "fake a login" , .session = AFB_SESSION_NONE }, - {.verb = "logout" , .callback = logout , .auth = NULL, + {.verb = "logout" , .callback = logout , .info = "log the current user out", .session = AFB_SESSION_NONE }, - {.verb = "get" , .callback = get , .auth = NULL, + {.verb = "get" , .callback = get , .info = "get data" , .session = AFB_SESSION_NONE }, - {.verb = "fake-auth" , .callback = fake_auth , .auth = NULL, + {.verb = "fake-auth" , .callback = fake_auth , .info = "fake an authentication" , .session = AFB_SESSION_NONE }, - {NULL} + { } }; const afb_binding_t afbBindingExport = { .api = "identity", - .specification = NULL, + .specification = "Identity-agent API", .info = "AGL identity service", .verbs = verbs, - .preinit = NULL, .init = service_init, .onevent = onevent, - .noconcurrency = 0 }; /* vim: set colorcolumn=80: */ diff --git a/src/agl-identity-common.h b/src/agl-identity-common.h new file mode 100644 index 0000000..1f0b16c --- /dev/null +++ b/src/agl-identity-common.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 Konsulko Group + * Author: Raquel Medina + * + * 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 AGL_IDENTITY_COMMON_H +#define AGL_IDENTITY_COMMON_H + +#define _GNU_SOURCE +#define AFB_BINDING_VERSION 3 +#include + +afb_api_t get_local_api(void); + +#endif // AGL_IDENTITY_COMMON_H diff --git a/src/aia-get.c b/src/aia-get.c index 56c82b0..4536e25 100644 --- a/src/aia-get.c +++ b/src/aia-get.c @@ -27,26 +27,6 @@ #include "curl-wrap.h" #include "oidc-agent.h" -/* -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - - -#include "u2f-bluez.h" -*/ - - struct keyrequest { struct keyrequest *next; int dead; diff --git a/src/curl-wrap.c b/src/curl-wrap.c index 9f010fb..626f321 100644 --- a/src/curl-wrap.c +++ b/src/curl-wrap.c @@ -69,15 +69,15 @@ int curl_wrap_perform(CURL *curl, char **result, size_t *size) buffer.size = 0; buffer.data = NULL; - /* Perform the request, res will get the return code */ + /* Perform the request, res will get the return code */ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); - /* Perform the request, res will get the return code */ + /* Perform the request, res will get the return code */ code = curl_easy_perform(curl); rc = code == CURLE_OK; - /* Check for no errors */ + /* Check for no errors */ if (rc) { /* no error */ if (size) diff --git a/src/curl-wrap.h b/src/curl-wrap.h index 2e44f47..dcdcef3 100644 --- a/src/curl-wrap.h +++ b/src/curl-wrap.h @@ -20,9 +20,6 @@ #include -extern char *curl_wrap_url (const char *base, const char *path, - const char *const *query, size_t * size); - extern int curl_wrap_perform (CURL * curl, char **result, size_t * size); extern void curl_wrap_do(CURL *curl, void (*callback)(void *closure, int status, CURL *curl, const char *result, size_t size), void *closure); diff --git a/src/test-aia-uds-bluez.c b/src/test-aia-uds-bluez.c deleted file mode 100644 index 4a084a5..0000000 --- a/src/test-aia-uds-bluez.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2015, 2016, 2017 "IoT.bzh" - * Author: José Bollo - * - * 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. - */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#include - -#include "aia-uds-bluez.h" - - -void p(const char *tag, const struct aia_uds_value *value) -{ - printf("%10s %c %.*s\n", tag, value->changed?'*':' ', (int)value->length, value->data); -} - -void onchg(const struct aia_uds *uds) -{ - printf("\n"); - p("first name", &uds->first_name); - p("last name", &uds->last_name); - p("email", &uds->email); - p("language", &uds->language); -} - -int main() -{ - sd_bus *bus; - sd_id128_t id; - int rc; - - aia_uds_set_on_change(onchg); - rc = sd_bus_default_system(&bus); - rc = sd_id128_randomize(&id); - rc = sd_bus_set_server(bus, 1, id); - rc = sd_bus_start(bus); - rc = aia_uds_init(bus); - rc = aia_uds_advise(1, NULL, NULL); - for (;;) { - rc = sd_bus_process(bus, NULL); - if (rc < 0) - break; - else if (rc == 0) - rc = sd_bus_wait(bus, (uint64_t) -1); - } -} - -- cgit 1.2.3-korg