summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-08-05 20:34:43 +0200
committerStefan Metzmacher <metze@samba.org>2011-08-12 16:46:43 +0200
commit42cde0480bd6a5e2dddaa66917e1fa71e6a4edcd (patch)
treeeca7dea12b5b8db4a26981fe1f2c78a34afbc752
parent81d3f92155856891ee0ac74cada3bbdd3e7670e1 (diff)
downloadsamba-42cde0480bd6a5e2dddaa66917e1fa71e6a4edcd.tar.gz
samba-42cde0480bd6a5e2dddaa66917e1fa71e6a4edcd.tar.bz2
samba-42cde0480bd6a5e2dddaa66917e1fa71e6a4edcd.zip
s3:smb2_server: make sure we prefer responses over requests on the client socket
metze Autobuild-User: Stefan Metzmacher <metze@samba.org> Autobuild-Date: Fri Aug 12 16:46:43 CEST 2011 on sn-devel-104
-rw-r--r--source3/smbd/smb2_server.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index e40c594428..6fc4b5d702 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -1826,6 +1826,8 @@ void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
}
}
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
+
static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
{
struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
@@ -1833,17 +1835,24 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
struct smbd_server_connection *sconn = req->sconn;
int ret;
int sys_errno;
+ NTSTATUS status;
ret = tstream_writev_queue_recv(subreq, &sys_errno);
TALLOC_FREE(subreq);
TALLOC_FREE(req);
if (ret == -1) {
- NTSTATUS status = map_nt_error_from_unix(sys_errno);
+ status = map_nt_error_from_unix(sys_errno);
DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
nt_errstr(status)));
smbd_server_connection_terminate(sconn, nt_errstr(status));
return;
}
+
+ status = smbd_smb2_request_next_incoming(sconn);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbd_server_connection_terminate(sconn, nt_errstr(status));
+ return;
+ }
}
NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
@@ -2450,12 +2459,47 @@ static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
static void smbd_smb2_request_incoming(struct tevent_req *subreq);
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
+{
+ size_t max_send_queue_len;
+ size_t cur_send_queue_len;
+ struct tevent_req *subreq;
+
+ if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
+ /*
+ * if there is already a smbd_smb2_request_read
+ * pending, we are done.
+ */
+ return NT_STATUS_OK;
+ }
+
+ max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
+ cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
+
+ if (cur_send_queue_len > max_send_queue_len) {
+ /*
+ * if we have a lot of requests to send,
+ * we wait until they are on the wire until we
+ * ask for the next request.
+ */
+ return NT_STATUS_OK;
+ }
+
+ /* ask for the next request */
+ subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
+
+ return NT_STATUS_OK;
+}
+
void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
const uint8_t *inbuf, size_t size)
{
NTSTATUS status;
struct smbd_smb2_request *req = NULL;
- struct tevent_req *subreq;
DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
(unsigned int)size));
@@ -2484,13 +2528,11 @@ void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
return;
}
- /* ask for the next request */
- subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
- if (subreq == NULL) {
- smbd_server_connection_terminate(sconn, "no memory for reading");
+ status = smbd_smb2_request_next_incoming(sconn);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbd_server_connection_terminate(sconn, nt_errstr(status));
return;
}
- tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
sconn->num_requests++;
}
@@ -2542,13 +2584,11 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq)
}
next:
- /* ask for the next request (this constructs the main loop) */
- subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
- if (subreq == NULL) {
- smbd_server_connection_terminate(sconn, "no memory for reading");
+ status = smbd_smb2_request_next_incoming(sconn);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbd_server_connection_terminate(sconn, nt_errstr(status));
return;
}
- tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
sconn->num_requests++;