s4:ldap_server: add call->wait_send/recv infrastructure
authorStefan Metzmacher <metze@samba.org>
Thu, 11 May 2017 14:51:15 +0000 (16:51 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 15 Jun 2017 07:13:22 +0000 (09:13 +0200)
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 <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/ldap_server/ldap_server.c
source4/ldap_server/ldap_server.h

index 062c3fc4b56782ab548f2a22046c1f83536d8e7c..6a6053206b29ec15b833daf1e3d137d932a9d2cc 100644 (file)
@@ -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;
index 337c974aaaeea8cb6b014644b3d6e6dbd0aefeda..d3e31fb1eec175fe21307f0853e271d688bfdbf8 100644 (file)
@@ -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);