From dc115d8a6aa1a656522c4f11c89e11d61360fd05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 28 Jun 2016 11:40:16 +0200
Subject: [PATCH 091/102] rdp: add ability to forward reply to the client
request
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In cases where the InfoPipe servers just as a middle-man between
the DataProvider and a client we can simply forward the reply
reducing amount of coded needed in the InfoPipe.
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit a40d9cc11d17d9c3c22a0462cd8c419d1e79ffb8)
---
src/responder/common/data_provider/rdp.h | 20 ++
src/responder/common/data_provider/rdp_message.c | 260 +++++++++++++++++------
src/responder/ifp/ifp_domains.c | 78 +------
3 files changed, 220 insertions(+), 138 deletions(-)
diff --git a/src/responder/common/data_provider/rdp.h b/src/responder/common/data_provider/rdp.h
index 8a3ec803d8ea7914e2a54661e31dec084586582a..f0aed179a3d33de0462591e6c0bcd3c518105707 100644
--- a/src/responder/common/data_provider/rdp.h
+++ b/src/responder/common/data_provider/rdp.h
@@ -54,6 +54,26 @@ errno_t _rdp_message_recv(struct tevent_req *req,
#define rdp_message_recv(req, ...) \
_rdp_message_recv(req, ##__VA_ARGS__, DBUS_TYPE_INVALID)
+/**
+ * Send D-Bus message to Data Provider but instead of returning the reply
+ * to the caller it forwards the reply to the client request. No further
+ * processing is required by the caller. In case of a failure the client
+ * request is freed since there is nothing we can do.
+ */
+void _rdp_message_send_and_reply(struct sbus_request *sbus_req,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ ...);
+
+#define rdp_message_send_and_reply(sbus_req, rctx, domain, path, iface, \
+ method, ...) \
+ _rdp_message_send_and_reply(sbus_req, rctx, domain, path, iface, method, \
+ ##__VA_ARGS__, DBUS_TYPE_INVALID)
+
errno_t rdp_register_client(struct be_conn *be_conn,
const char *client_name);
diff --git a/src/responder/common/data_provider/rdp_message.c b/src/responder/common/data_provider/rdp_message.c
index 78af6f8967b378536b6456274fbcac4b609d1033..e226401567e4a1b2b9784a9aba21540ff5f0bc8d 100644
--- a/src/responder/common/data_provider/rdp_message.c
+++ b/src/responder/common/data_provider/rdp_message.c
@@ -53,104 +53,72 @@ static errno_t rdp_error_to_errno(DBusError *error)
return EIO;
}
-struct rdp_message_state {
- struct DBusMessage *reply;
-};
-
-static int rdp_message_state_destructor(struct rdp_message_state *state)
+static errno_t
+rdp_message_send_internal(struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ DBusPendingCallNotifyFunction notify_fn,
+ void *notify_fn_data,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ va_list va)
{
- if (state->reply != NULL) {
- dbus_message_unref(state->reply);
- }
-
- return 0;
-}
-
-static void rdp_message_done(DBusPendingCall *pending, void *ptr);
-
-struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx,
- struct resp_ctx *rctx,
- struct sss_domain_info *domain,
- const char *path,
- const char *iface,
- const char *method,
- int first_arg_type,
- ...)
-{
- struct rdp_message_state *state;
struct be_conn *be_conn;
- struct tevent_req *req;
- DBusMessage *msg;
+ DBusMessage *msg = NULL;
dbus_bool_t bret;
errno_t ret;
- va_list va;
-
- req = tevent_req_create(mem_ctx, &state, struct rdp_message_state);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
- return NULL;
- }
-
- talloc_set_destructor(state, rdp_message_state_destructor);
ret = sss_dp_get_domain_conn(rctx, domain->conn_name, &be_conn);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
"%s is not available!\n", domain->name);
- ret = ERR_INTERNAL;
- goto immediately;
+ goto done;
}
msg = dbus_message_new_method_call(NULL, path, iface, method);
if (msg == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create message\n");
ret = ENOMEM;
- goto immediately;
+ goto done;
}
- va_start(va, first_arg_type);
bret = dbus_message_append_args_valist(msg, first_arg_type, va);
- va_end(va);
if (!bret) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n");
ret = EIO;
- goto immediately;
+ goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "DP Request: %s %s.%s\n", path, iface, method);
- ret = sbus_conn_send(be_conn->conn, msg, 30000,
- rdp_message_done, req, NULL);
+ ret = sbus_conn_send(be_conn->conn, msg, 3000,
+ notify_fn, notify_fn_data, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider "
"[%d]: %s\n", ret, sss_strerror(ret));
- goto immediately;
+ goto done;
}
- return req;
+ ret = EOK;
-immediately:
- if (ret == EOK) {
- tevent_req_done(req);
- } else {
- tevent_req_error(req, ret);
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
}
- tevent_req_post(req, rctx->ev);
- return req;
+ return ret;
}
-static void rdp_message_done(DBusPendingCall *pending, void *ptr)
+static errno_t rdp_process_pending_call(DBusPendingCall *pending,
+ DBusMessage **_reply)
{
- struct rdp_message_state *state;
- DBusMessage *reply = NULL;
- struct tevent_req *req;
- DBusError error;
+ DBusMessage *reply;
dbus_bool_t bret;
+ DBusError error;
errno_t ret;
- req = talloc_get_type(ptr, struct tevent_req);
- state = tevent_req_data(req, struct rdp_message_state);
+ *_reply = NULL;
dbus_error_init(&error);
@@ -165,9 +133,8 @@ static void rdp_message_done(DBusPendingCall *pending, void *ptr)
switch (dbus_message_get_type(reply)) {
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
DEBUG(SSSDBG_TRACE_FUNC, "DP Success\n");
- state->reply = reply;
ret = EOK;
- goto done;
+ break;
case DBUS_MESSAGE_TYPE_ERROR:
bret = dbus_set_error_from_message(&error, reply);
@@ -180,28 +147,105 @@ static void rdp_message_done(DBusPendingCall *pending, void *ptr)
DEBUG(SSSDBG_CRIT_FAILURE, "DP Error [%s]: %s\n",
error.name, (error.message == NULL ? "(null)" : error.message));
ret = rdp_error_to_errno(&error);
- goto done;
+ break;
default:
+ dbus_message_unref(reply);
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected type?\n");
ret = ERR_INTERNAL;
goto done;
}
- ret = ERR_INTERNAL;
+ *_reply = reply;
done:
dbus_pending_call_unref(pending);
dbus_error_free(&error);
+ return ret;
+}
+
+struct rdp_message_state {
+ struct DBusMessage *reply;
+};
+
+static int rdp_message_state_destructor(struct rdp_message_state *state)
+{
+ if (state->reply != NULL) {
+ dbus_message_unref(state->reply);
+ }
+
+ return 0;
+}
+
+static void rdp_message_done(DBusPendingCall *pending, void *ptr);
+
+struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ ...)
+{
+ struct rdp_message_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+ va_list va;
+
+ req = tevent_req_create(mem_ctx, &state, struct rdp_message_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ talloc_set_destructor(state, rdp_message_state_destructor);
+
+ va_start(va, first_arg_type);
+ ret = rdp_message_send_internal(rctx, domain, rdp_message_done, req,
+ path, iface, method, first_arg_type, va);
+ va_end(va);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto immediately;
+ }
+
+ return req;
+
+immediately:
if (ret == EOK) {
tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, rctx->ev);
+
+ return req;
+}
+
+static void rdp_message_done(DBusPendingCall *pending, void *ptr)
+{
+ struct rdp_message_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = talloc_get_type(ptr, struct tevent_req);
+ state = tevent_req_data(req, struct rdp_message_state);
+
+ ret = rdp_process_pending_call(pending, &state->reply);
+ if (ret != EOK) {
+ if (state->reply != NULL) {
+ dbus_message_unref(state->reply);
+ }
+
+ state->reply = NULL;
+
+ tevent_req_error(req, ret);
return;
}
- if (reply != NULL) {
- dbus_message_unref(reply);
- }
- tevent_req_error(req, ret);
+ tevent_req_done(req);
}
errno_t _rdp_message_recv(struct tevent_req *req,
@@ -241,3 +285,85 @@ done:
return ret;
}
+static void rdp_message_send_and_reply_done(DBusPendingCall *pending,
+ void *ptr);
+
+void _rdp_message_send_and_reply(struct sbus_request *sbus_req,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ ...)
+{
+ errno_t ret;
+ va_list va;
+
+ va_start(va, first_arg_type);
+ ret = rdp_message_send_internal(rctx, domain,
+ rdp_message_send_and_reply_done, sbus_req,
+ path, iface, method, first_arg_type, va);
+ va_end(va);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ talloc_free(sbus_req);
+ }
+}
+
+static void rdp_message_send_and_reply_done(DBusPendingCall *pending,
+ void *ptr)
+{
+ struct sbus_request *sbus_req;
+ DBusMessage *reply = NULL;
+ dbus_uint32_t serial;
+ const char *sender;
+ dbus_bool_t dbret;
+ errno_t ret;
+
+ sbus_req = talloc_get_type(ptr, struct sbus_request);
+
+ ret = rdp_process_pending_call(pending, &reply);
+ if (reply == NULL) {
+ /* Something bad happened. Just kill the request. */
+ ret = EIO;
+ goto done;
+ }
+
+ /* Otherwise we have a valid reply and we do not care about returned
+ * value. We set destination and serial in reply to point to the original
+ * client request. */
+
+ sender = dbus_message_get_sender(sbus_req->message);
+ serial = dbus_message_get_serial(sbus_req->message);
+
+ dbret = dbus_message_set_destination(reply, sender);
+ if (dbret == false) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set reply sender!\n");
+ ret = EIO;
+ goto done;
+ }
+
+ dbret = dbus_message_set_reply_serial(reply, serial);
+ if (dbret == false) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set reply serial!\n");
+ ret = EIO;
+ goto done;
+ }
+
+ sbus_request_finish(sbus_req, reply);
+
+ ret = EOK;
+
+done:
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ if (ret != EOK) {
+ /* Something bad happend, just kill the request. */
+ talloc_free(sbus_req);
+ }
+}
diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c
index 5333b25275e0847015f9cdd294eab5dbdda32f6c..8bfd39feb39822921ea703d8a89ac372e0ad5410 100644
--- a/src/responder/ifp/ifp_domains.c
+++ b/src/responder/ifp/ifp_domains.c
@@ -538,14 +538,11 @@ void ifp_dom_get_parent_domain(struct sbus_request *dbus_req,
dom->parent->name);
}
-static void ifp_domains_domain_is_online_done(struct tevent_req *req);
-
int ifp_domains_domain_is_online(struct sbus_request *sbus_req,
void *data)
{
struct ifp_ctx *ifp_ctx;
struct sss_domain_info *dom;
- struct tevent_req *req;
DBusError *error;
ifp_ctx = talloc_get_type(data, struct ifp_ctx);
@@ -558,49 +555,18 @@ int ifp_domains_domain_is_online(struct sbus_request *sbus_req,
return EOK;
}
- req = rdp_message_send(sbus_req, ifp_ctx->rctx, dom, DP_PATH,
- IFACE_DP_BACKEND, IFACE_DP_BACKEND_ISONLINE,
- DBUS_TYPE_STRING, &dom->name);
- if (req == NULL) {
- return ENOMEM;
- }
-
- tevent_req_set_callback(req, ifp_domains_domain_is_online_done, sbus_req);
+ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH,
+ IFACE_DP_BACKEND, IFACE_DP_BACKEND_ISONLINE,
+ DBUS_TYPE_STRING, &dom->name);
return EOK;
}
-static void ifp_domains_domain_is_online_done(struct tevent_req *req)
-{
- struct sbus_request *sbus_req;
- DBusError *error;
- bool is_online;
- errno_t ret;
-
- sbus_req = tevent_req_callback_data(req, struct sbus_request);
-
- ret = rdp_message_recv(req, DBUS_TYPE_BOOLEAN, &is_online);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Unable to get online status [%d]: %s\n",
- ret, sss_strerror(ret));
- error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
- "Unable to get online status [%d]: %s",
- ret, sss_strerror(ret));
- sbus_request_fail_and_finish(sbus_req, error);
- return;
- }
-
- iface_ifp_domains_domain_IsOnline_finish(sbus_req, is_online);
-}
-
-static void ifp_domains_domain_list_services_done(struct tevent_req *req);
-
int ifp_domains_domain_list_services(struct sbus_request *sbus_req,
void *data)
{
struct ifp_ctx *ifp_ctx;
struct sss_domain_info *dom;
- struct tevent_req *req;
DBusError *error;
ifp_ctx = talloc_get_type(data, struct ifp_ctx);
@@ -613,40 +579,10 @@ int ifp_domains_domain_list_services(struct sbus_request *sbus_req,
return EOK;
}
- req = rdp_message_send(sbus_req, ifp_ctx->rctx, dom, DP_PATH,
- IFACE_DP_FAILOVER, IFACE_DP_FAILOVER_LISTSERVICES,
- DBUS_TYPE_STRING, &dom->name);
- if (req == NULL) {
- return ENOMEM;
- }
-
- tevent_req_set_callback(req, ifp_domains_domain_list_services_done, sbus_req);
+ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH,
+ IFACE_DP_FAILOVER,
+ IFACE_DP_FAILOVER_LISTSERVICES,
+ DBUS_TYPE_STRING, &dom->name);
return EOK;
}
-
-static void ifp_domains_domain_list_services_done(struct tevent_req *req)
-{
- struct sbus_request *sbus_req;
- DBusError *error;
- int num_services;
- const char **services;
- errno_t ret;
-
- sbus_req = tevent_req_callback_data(req, struct sbus_request);
-
- ret = rdp_message_recv(req, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
- &services, &num_services);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Unable to get failover services [%d]: %s\n",
- ret, sss_strerror(ret));
- error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
- "Unable to get failover services [%d]: %s",
- ret, sss_strerror(ret));
- sbus_request_fail_and_finish(sbus_req, error);
- return;
- }
-
- iface_ifp_domains_domain_ListServices_finish(sbus_req, services,
- num_services);
-}
--
2.4.11