Beispiel #1
0
/*
  perform the send side of a async dcerpc request
*/
static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, 
					       const struct GUID *object,
					       uint16_t opnum,
					       bool async,
					       DATA_BLOB *stub_data)
{
	struct rpc_request *req;

	p->conn->transport.recv_data = dcerpc_recv_data;

	req = talloc(p, struct rpc_request);
	if (req == NULL) {
		return NULL;
	}

	req->p = p;
	req->call_id = next_call_id(p->conn);
	req->status = NT_STATUS_OK;
	req->state = RPC_REQUEST_QUEUED;
	req->payload = data_blob(NULL, 0);
	req->flags = 0;
	req->fault_code = 0;
	req->async_call = async;
	req->ignore_timeout = false;
	req->async.callback = NULL;
	req->async.private_data = NULL;
	req->recv_handler = NULL;

	if (object != NULL) {
		req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
		if (req->object == NULL) {
			talloc_free(req);
			return NULL;
		}
	} else {
		req->object = NULL;
	}

	req->opnum = opnum;
	req->request_data.length = stub_data->length;
	req->request_data.data = talloc_reference(req, stub_data->data);
	if (req->request_data.length && req->request_data.data == NULL) {
		return NULL;
	}

	DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
	talloc_set_destructor(req, dcerpc_req_dequeue);

	dcerpc_ship_next_request(p->conn);

	if (p->request_timeout) {
		event_add_timed(dcerpc_event_context(p), req, 
				timeval_current_ofs(p->request_timeout, 0), 
				dcerpc_timeout_handler, req);
	}

	return req;
}
Beispiel #2
0
/*
  perform the receive side of a async dcerpc request
*/
NTSTATUS dcerpc_request_recv(struct rpc_request *req,
			     TALLOC_CTX *mem_ctx,
			     DATA_BLOB *stub_data)
{
	NTSTATUS status;

	while (req->state != RPC_REQUEST_DONE) {
		struct tevent_context *ctx = dcerpc_event_context(req->p);
		if (event_loop_once(ctx) != 0) {
			return NT_STATUS_CONNECTION_DISCONNECTED;
		}
	}
	*stub_data = req->payload;
	status = req->status;
	if (stub_data->data) {
		stub_data->data = talloc_steal(mem_ctx, stub_data->data);
	}
	if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
		req->p->last_fault_code = req->fault_code;
	}
	talloc_unlink(talloc_parent(req), req);
	return status;
}
Beispiel #3
0
/*
  test the TestSleep interface
*/
static bool test_sleep(struct torture_context *tctx,
						  struct dcerpc_pipe *p)
{
	int i;
	NTSTATUS status;
#define ASYNC_COUNT 3
	struct rpc_request *req[ASYNC_COUNT];
	struct echo_TestSleep r[ASYNC_COUNT];
	bool done[ASYNC_COUNT];
	struct timeval snd[ASYNC_COUNT];
	struct timeval rcv[ASYNC_COUNT];
	struct timeval diff[ASYNC_COUNT];
	struct tevent_context *ctx;
	int total_done = 0;

	if (torture_setting_bool(tctx, "quick", false)) {
		torture_skip(tctx, "TestSleep disabled - use \"torture:quick=no\" to enable\n");
	}
	torture_comment(tctx, "Testing TestSleep - use \"torture:quick=yes\" to disable\n");

	for (i=0;i<ASYNC_COUNT;i++) {
		done[i]		= false;
		snd[i]		= timeval_current();
		rcv[i]		= timeval_zero();
		r[i].in.seconds = ASYNC_COUNT-i;
		req[i] = dcerpc_echo_TestSleep_send(p, tctx, &r[i]);
		torture_assert(tctx, req[i], "Failed to send async sleep request\n");
	}

	ctx = dcerpc_event_context(p);
	while (total_done < ASYNC_COUNT) {
		torture_assert(tctx, event_loop_once(ctx) == 0, 
					   "Event context loop failed");
		for (i=0;i<ASYNC_COUNT;i++) {
			if (done[i] == false && req[i]->state == RPC_REQUEST_DONE) {
				int rounded_tdiff;
				total_done++;
				done[i] = true;
				rcv[i]	= timeval_current();
				diff[i]	= timeval_until(&snd[i], &rcv[i]);
				rounded_tdiff = (int)(0.5 + diff[i].tv_sec + (1.0e-6*diff[i].tv_usec));
				status	= dcerpc_ndr_request_recv(req[i]);
				torture_comment(tctx, "rounded_tdiff=%d\n", rounded_tdiff);
				torture_assert_ntstatus_ok(tctx, status, 
							talloc_asprintf(tctx, "TestSleep(%d) failed", i));
				torture_assert(tctx, r[i].out.result == r[i].in.seconds,
					talloc_asprintf(tctx, "Failed - Asked to sleep for %u seconds (server replied with %u seconds and the reply takes only %u seconds)", 
						r[i].out.result, r[i].in.seconds, (unsigned int)diff[i].tv_sec));
				torture_assert(tctx, r[i].out.result <= rounded_tdiff, 
					talloc_asprintf(tctx, "Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)", 
						r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec));
				if (r[i].out.result+1 == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else if (r[i].out.result == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (reply takes %u.%06u seconds - ok)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else {
						torture_comment(tctx, "(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
					/* TODO: let the test fail here, when we support async rpc on ncacn_np */
				}
			}
		}
	}
	torture_comment(tctx, "\n");
	return true;
}