summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-01-20 04:32:17 +0000
committerAndrew Tridgell <tridge@samba.org>2004-01-20 04:32:17 +0000
commit4d39861f991254aa381b8823476825e26a4d6da3 (patch)
tree75d838f3daf7932ecc83fc5370ffd5bd09ba51b9
parent1e1428605b01de36299c0832bce9bf9d29de0b66 (diff)
downloadsamba-4d39861f991254aa381b8823476825e26a4d6da3.tar.gz
samba-4d39861f991254aa381b8823476825e26a4d6da3.tar.bz2
samba-4d39861f991254aa381b8823476825e26a4d6da3.zip
avoid a copy of the data being input to the dcerpc server in the most
common case of there being no pending partial data and a full dcerpc packet being received. We should use this same model for the smb server. It gives us efficient memory usage while allowing for completely async socket operations. (This used to be commit 9aab321fb6e2f3499efd8ca5bc88ce2cb8e68219)
-rw-r--r--source4/rpc_server/dcerpc_server.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 46341e6db1..a4f5fb9768 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -689,15 +689,14 @@ static void dce_partial_advance(struct dcesrv_connection *dce_conn, uint32 offse
DATA_BLOB blob;
if (dce_conn->partial_input.length == offset) {
- free(dce_conn->partial_input.data);
- dce_conn->partial_input = data_blob(NULL, 0);
+ data_blob_free(&dce_conn->partial_input);
return;
}
blob = dce_conn->partial_input;
dce_conn->partial_input = data_blob(blob.data + offset,
- blob.length - offset);
- free(blob.data);
+ blob.length - offset);
+ data_blob_free(&blob);
}
/*
@@ -840,6 +839,32 @@ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
{
NTSTATUS status;
+ /* handle the very common case that the input contains a full packet and there
+ is no partial packet pending. In this case we can avoid a copy of the
+ data */
+ if (dce_conn->partial_input.length == 0) {
+ dce_conn->partial_input = *data;
+ /* make sure that dce_partial_advance doesn't free this data */
+ dce_conn->partial_input.free = NULL;
+ while (dce_full_packet(&dce_conn->partial_input)) {
+ status = dcesrv_input_process(dce_conn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+ if (dce_conn->partial_input.length) {
+ /* there was some data left over. We have to copy this
+ as the caller may free the data */
+ dce_conn->partial_input =
+ data_blob(dce_conn->partial_input.data,
+ dce_conn->partial_input.length);
+ if (!dce_conn->partial_input.data) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ return NT_STATUS_OK;
+ }
+
dce_conn->partial_input.data = Realloc(dce_conn->partial_input.data,
dce_conn->partial_input.length + data->length);
if (!dce_conn->partial_input.data) {