r2185: add a callback function to the dcerpc async API
authorAndrew Tridgell <tridge@samba.org>
Thu, 2 Sep 2004 12:03:16 +0000 (12:03 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:58:30 +0000 (12:58 -0500)
also add a demonstration of its use in the netlogon async example
(This used to be commit f2a0438c66b999189c1a2ad726e91efd0748eb90)

source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc.h
source4/torture/rpc/netlogon.c

index ec2269641933c61d2823a628c47f4df433459c42..55acf4625c850f2fcdcbeda2fce8a44c50674017 100644 (file)
@@ -631,6 +631,9 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
                        req->state = RPC_REQUEST_DONE;
                        req->status = status;
                        DLIST_REMOVE(p->pending, req);
+                       if (req->async.callback) {
+                               req->async.callback(req);
+                       }
                }
                return;
        }
@@ -655,6 +658,9 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
                req->status = status;
                req->state = RPC_REQUEST_DONE;
                DLIST_REMOVE(p->pending, req);
+               if (req->async.callback) {
+                       req->async.callback(req);
+               }
                return;
        }
 
@@ -664,6 +670,9 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
                req->status = NT_STATUS_NET_WRITE_FAULT;
                req->state = RPC_REQUEST_DONE;
                DLIST_REMOVE(p->pending, req);
+               if (req->async.callback) {
+                       req->async.callback(req);
+               }
                return;
        }
 
@@ -674,6 +683,9 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
                req->status = NT_STATUS_NET_WRITE_FAULT;
                req->state = RPC_REQUEST_DONE;
                DLIST_REMOVE(p->pending, req);
+               if (req->async.callback) {
+                       req->async.callback(req);
+               }
                return;
        }
 
@@ -686,6 +698,9 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
                        req->status = NT_STATUS_NO_MEMORY;
                        req->state = RPC_REQUEST_DONE;
                        DLIST_REMOVE(p->pending, req);
+                       if (req->async.callback) {
+                               req->async.callback(req);
+                       }
                        return;
                }
                memcpy(req->payload.data+req->payload.length, 
@@ -707,6 +722,10 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p,
        } else {
                req->flags &= ~DCERPC_PULL_BIGENDIAN;
        }
+
+       if (req->async.callback) {
+               req->async.callback(req);
+       }
 }
 
 
@@ -737,6 +756,7 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
        req->payload = data_blob(NULL, 0);
        req->flags = 0;
        req->fault_code = 0;
+       req->async.callback = NULL;
 
        init_dcerpc_hdr(p, &pkt);
 
index 1443e10927447796ac42c6d5e5a1625f00a3db35..0ec1abf55d739bf2520fec1cd0326dfd77a7dffb 100644 (file)
@@ -166,4 +166,9 @@ struct rpc_request {
                size_t struct_size;
                TALLOC_CTX *mem_ctx;
        } ndr;
+
+       struct {
+               void (*callback)(struct rpc_request *);
+               void *private;
+       } async;
 };
index d5acfa8c36dd3f009ab4694b3c593856b7c78030..5cb4caa9421b8ee767ac43293154ea621fa297b9 100644 (file)
@@ -1625,6 +1625,14 @@ static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 }
 
 
+static void async_callback(struct rpc_request *req)
+{
+       int *counter = req->async.private;
+       if (NT_STATUS_IS_OK(req->status)) {
+               (*counter)++;
+       }
+}
+
 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
        NTSTATUS status;
@@ -1636,6 +1644,7 @@ static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        struct creds_CredentialState creds_async[ASYNC_COUNT];
        struct rpc_request *req[ASYNC_COUNT];
        int i;
+       int async_counter = 0;
 
        if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
                return False;
@@ -1670,6 +1679,13 @@ static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 
                creds_async[i] = creds;
                req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
+
+               req[i]->async.callback = async_callback;
+               req[i]->async.private = &async_counter;
+
+               /* even with this flush per request a w2k3 server seems to 
+                  clag with multiple outstanding requests. bleergh. */
+               event_loop_once(dcerpc_event_context(p));
        }
 
        for (i=0;i<ASYNC_COUNT;i++) {
@@ -1677,18 +1693,18 @@ static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
                        printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
                               i, nt_errstr(status), nt_errstr(r.out.result));
-                       return False;
+                       break;
                }
 
                if (!creds_client_check(&creds_async[i], &a.cred)) {
                        printf("Credential chaining failed at async %d\n", i);
-                       return False;
+                       break;
                }
        }
 
-       printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", ASYNC_COUNT);
+       printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", async_counter);
 
-       return True;
+       return async_counter == ASYNC_COUNT;
 }