summaryrefslogtreecommitdiff
path: root/source4/rpc_server/dcerpc_server.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-01-20 05:54:17 +0000
committerAndrew Tridgell <tridge@samba.org>2004-01-20 05:54:17 +0000
commit7a4da9654e30ea96b326448c3e9111c2a5604f58 (patch)
tree628dbc1eeaf7034349708149e2a49d3fb402f65a /source4/rpc_server/dcerpc_server.c
parent4d39861f991254aa381b8823476825e26a4d6da3 (diff)
downloadsamba-7a4da9654e30ea96b326448c3e9111c2a5604f58.tar.gz
samba-7a4da9654e30ea96b326448c3e9111c2a5604f58.tar.bz2
samba-7a4da9654e30ea96b326448c3e9111c2a5604f58.zip
dcerpc server output now copes with the client blocking part way
through a read. This happens to also avoid a memcpy on output for dcerpc over tcp. (This used to be commit e7c53ad1856e299d82d84b5837189ae3191c32de)
Diffstat (limited to 'source4/rpc_server/dcerpc_server.c')
-rw-r--r--source4/rpc_server/dcerpc_server.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index a4f5fb9768..0553537cb5 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -885,14 +885,23 @@ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
}
/*
- retrieve some output from a dcerpc server. The amount of data that
- is wanted is in data->length and data->data is already allocated
- to hold that much data.
+ retrieve some output from a dcerpc server
+ The caller supplies a function that will be called to do the
+ actual output.
+
+ The first argument to write_fn() will be 'private', the second will
+ be a pointer to a buffer containing the data to be sent and the 3rd
+ will be the number of bytes to be sent.
+
+ write_fn() should return the number of bytes successfully written.
*/
-NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, DATA_BLOB *data)
+NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
+ void *private,
+ ssize_t (*write_fn)(void *, const void *, size_t))
{
struct dcesrv_call_state *call;
struct dcesrv_call_reply *rep;
+ ssize_t nwritten;
call = dce_conn->call_list;
if (!call || !call->replies) {
@@ -900,13 +909,15 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, DATA_BLOB *data)
}
rep = call->replies;
- if (data->length >= rep->data.length) {
- data->length = rep->data.length;
+ nwritten = write_fn(private, rep->data.data, rep->data.length);
+ if (nwritten == -1) {
+ /* TODO: hmm, how do we cope with this? destroy the
+ connection perhaps? */
+ return NT_STATUS_UNSUCCESSFUL;
}
- memcpy(data->data, rep->data.data, data->length);
- rep->data.length -= data->length;
- rep->data.data += data->length;
+ rep->data.length -= nwritten;
+ rep->data.data += nwritten;
if (rep->data.length == 0) {
/* we're done with this section of the call */
@@ -922,6 +933,30 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, DATA_BLOB *data)
return NT_STATUS_OK;
}
+
+/*
+ write_fn() for dcesrv_output_blob()
+*/
+static ssize_t dcesrv_output_blob_write_fn(void *private, const void *buf, size_t count)
+{
+ DATA_BLOB *blob = private;
+ if (count < blob->length) {
+ blob->length = count;
+ }
+ memcpy(blob->data, buf, blob->length);
+ return blob->length;
+}
+
+/*
+ a simple wrapper for dcesrv_output() for when we want to output
+ into a data blob
+*/
+NTSTATUS dcesrv_output_blob(struct dcesrv_connection *dce_conn,
+ DATA_BLOB *blob)
+{
+ return dcesrv_output(dce_conn, blob, dcesrv_output_blob_write_fn);
+}
+
/*
initialise the dcerpc server context
*/