}
}
+static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
+static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
void *private_data)
DATA_BLOB payload;
bool ok;
struct tevent_req *subreq;
+ bool use_trans = true;
if (state->object) {
flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
+ if (!frag->is_last) {
+ use_trans = false;
+ }
+
+ if (frag->conn->transport.use_trans_fn == NULL) {
+ use_trans = false;
+ }
+
+ if (frag->conn->loop.subreq != NULL) {
+ use_trans = false;
+ }
+
+ if (frag->conn->features.concurrent_multiplex) {
+ use_trans = false;
+ }
+
+ if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
+ use_trans = false;
+ }
+
+ if (use_trans) {
+ frag->subreq_wait1 = tevent_queue_wait_send(frag,
+ frag->ev,
+ frag->conn->transport.write_queue);
+ if (tevent_req_nomem(req, frag->subreq_wait1)) {
+ return;
+ }
+ tevent_req_set_callback(frag->subreq_wait1,
+ dcerpc_do_request_out_frag_trans_wait1,
+ frag);
+ /*
+ * we need to block reads until our write is
+ * the next in the write queue.
+ */
+ frag->conn->loop.subreq = frag->subreq_wait1;
+ frag->conn->loop.ev = frag->ev;
+ }
+
/*
- * TODO: add smb_trans handling for ncacn_np
- *
* We need to add a dcerpc_write_fragment_queue_send/recv()
*/
dcerpc_do_request_out_frag_done,
frag);
+ if (use_trans) {
+ frag->subreq_wait2 = tevent_queue_wait_send(frag,
+ frag->ev,
+ frag->conn->transport.write_queue);
+ if (tevent_req_nomem(req, frag->subreq_wait2)) {
+ return;
+ }
+ tevent_req_set_callback(frag->subreq_wait2,
+ dcerpc_do_request_out_frag_trans_wait2,
+ frag);
+ }
+
if (!frag->is_last) {
return;
}
}
}
+static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
+{
+ struct dcerpc_do_request_out_frag *frag =
+ tevent_req_callback_data(subreq,
+ struct dcerpc_do_request_out_frag);
+ struct tevent_req *req = frag->req;
+ NTSTATUS status;
+ bool ok;
+
+ /*
+ * TODO; what if the caller has been free'ed?
+ */
+
+ frag->subreq_wait1 = NULL;
+ frag->conn->loop.subreq = NULL;
+
+ ok = tevent_queue_wait_recv(subreq);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ TALLOC_FREE(frag);
+ if (req) {
+ tevent_req_nterror(req, status);
+ }
+ //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
+ /*
+ * We added 3 entries into the queue,
+ * wait1, writev and wait2.
+ *
+ * There's more to write, we should not block
+ * further writev calls for a trans call.
+ *
+ * The wait2 stage will trigger the read.
+ */
+ TALLOC_FREE(subreq);
+ return;
+ }
+
+ /*
+ * we don't need wait2 anymore, we're sure that
+ * we'll do a trans call.
+ */
+ TALLOC_FREE(frag->subreq_wait2);
+
+ status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frag);
+ if (req) {
+ tevent_req_nterror(req, status);
+ }
+ //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ /* we free subreq after tstream_cli_np_use_trans */
+ TALLOC_FREE(subreq);
+
+ status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frag);
+ if (req) {
+ tevent_req_nterror(req, status);
+ }
+ //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
+ return;
+ }
+}
+
static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
{
struct dcerpc_do_request_out_frag *frag =
return;
}
+ if (frag->subreq_wait2 != NULL) {
+ return;
+ }
+
if (frag->is_last) {
TALLOC_FREE(frag);
return;
dcerpc_do_request_out_frag_next(req, NULL);
}
+static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
+{
+ struct dcerpc_do_request_out_frag *frag =
+ tevent_req_callback_data(subreq,
+ struct dcerpc_do_request_out_frag);
+ struct tevent_req *req = frag->req;
+ NTSTATUS status;
+ bool ok;
+
+ frag->subreq_wait2 = NULL;
+
+ ok = tevent_queue_wait_recv(subreq);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ TALLOC_FREE(frag);
+ if (req) {
+ tevent_req_nterror(req, status);
+ }
+ //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ TALLOC_FREE(subreq);
+
+ status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frag);
+ if (req) {
+ tevent_req_nterror(req, status);
+ }
+ //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ TALLOC_FREE(frag);
+
+ /* we need to wait for incoming pdus */
+}
+
static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
struct ncacn_packet *pkt,
DATA_BLOB frag)