From: Stefan Metzmacher Date: Thu, 11 May 2017 14:51:15 +0000 (+0200) Subject: s4:ldap_server: add call->wait_send/recv infrastructure X-Git-Tag: ldb-1.1.31~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=900ab851a77ca0cb272fa1a6b0894cac7c41510f;p=thirdparty%2Fsamba.git s4:ldap_server: add call->wait_send/recv infrastructure If it is set by the dispatch functions, the core server will use call->wait_send() and wait for it to finally return frim call->wait_recv() before it asks for the next incoming pdu. This can be used to implement bind as async operations. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 062c3fc4b56..6a6053206b2 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -578,7 +578,8 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq) conn->active_call = subreq; } - +static void ldapsrv_call_wait_done(struct tevent_req *subreq); +static void ldapsrv_call_writev_start(struct ldapsrv_call *call); static void ldapsrv_call_writev_done(struct tevent_req *subreq); static void ldapsrv_call_process_done(struct tevent_req *subreq) @@ -588,7 +589,6 @@ static void ldapsrv_call_process_done(struct tevent_req *subreq) struct ldapsrv_call); struct ldapsrv_connection *conn = call->conn; NTSTATUS status; - DATA_BLOB blob = data_blob_null; conn->active_call = NULL; @@ -599,6 +599,61 @@ static void ldapsrv_call_process_done(struct tevent_req *subreq) return; } + if (call->wait_send != NULL) { + subreq = call->wait_send(call, + conn->connection->event.ctx, + call->wait_private); + if (subreq == NULL) { + ldapsrv_terminate_connection(conn, + "ldapsrv_call_process_done: " + "call->wait_send - no memory"); + return; + } + tevent_req_set_callback(subreq, + ldapsrv_call_wait_done, + call); + conn->active_call = subreq; + return; + } + + ldapsrv_call_writev_start(call); +} + +static void ldapsrv_call_wait_done(struct tevent_req *subreq) +{ + struct ldapsrv_call *call = + tevent_req_callback_data(subreq, + struct ldapsrv_call); + struct ldapsrv_connection *conn = call->conn; + NTSTATUS status; + + conn->active_call = NULL; + + status = call->wait_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + const char *reason; + + reason = talloc_asprintf(call, "ldapsrv_call_wait_done: " + "call->wait_recv() - %s", + nt_errstr(status)); + if (reason == NULL) { + reason = nt_errstr(status); + } + + ldapsrv_terminate_connection(conn, reason); + return; + } + + ldapsrv_call_writev_start(call); +} + +static void ldapsrv_call_writev_start(struct ldapsrv_call *call) +{ + struct ldapsrv_connection *conn = call->conn; + DATA_BLOB blob = data_blob_null; + struct tevent_req *subreq = NULL; + /* build all the replies into a single blob */ while (call->replies) { DATA_BLOB b; diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h index 337c974aaae..d3e31fb1eec 100644 --- a/source4/ldap_server/ldap_server.h +++ b/source4/ldap_server/ldap_server.h @@ -73,6 +73,12 @@ struct ldapsrv_call { } *replies; struct iovec out_iov; + struct tevent_req *(*wait_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data); + NTSTATUS (*wait_recv)(struct tevent_req *req); + void *wait_private; + struct tevent_req *(*postprocess_send)(TALLOC_CTX *mem_ctx, struct tevent_context *ev, void *private_data);