summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-28 05:09:42 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:04:52 -0500
commitaa19318fd513fb4d6a36793b96fb7ffa66622d6f (patch)
tree6ec045ea70e727e3c95489a5230d00d36c0b4c9d
parentd668ec53b355de04f45279f14906ab5af116183e (diff)
downloadsamba-aa19318fd513fb4d6a36793b96fb7ffa66622d6f.tar.gz
samba-aa19318fd513fb4d6a36793b96fb7ffa66622d6f.tar.bz2
samba-aa19318fd513fb4d6a36793b96fb7ffa66622d6f.zip
r3307: fixed the send side of the smb_server code to be non-blocking. This
means the whole of the SMB handling code is now non-blocking. (This used to be commit 30acedb943f0170d30e7b08925280d0dffc7873e)
-rw-r--r--source4/smb_server/request.c18
-rw-r--r--source4/smb_server/smb_server.c42
-rw-r--r--source4/smb_server/smb_server.h7
3 files changed, 49 insertions, 18 deletions
diff --git a/source4/smb_server/request.c b/source4/smb_server/request.c
index 4ca9c9ffda..3095d0b70c 100644
--- a/source4/smb_server/request.c
+++ b/source4/smb_server/request.c
@@ -241,24 +241,16 @@ void req_grow_data(struct smbsrv_request *req, uint_t new_size)
*/
void req_send_reply_nosign(struct smbsrv_request *req)
{
- NTSTATUS status;
- DATA_BLOB tmp_blob;
- size_t sendlen;
-
if (req->out.size > NBT_HDR_SIZE) {
_smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
}
- tmp_blob.data = req->out.buffer;
- tmp_blob.length = req->out.size;
-
- status = socket_send(req->smb_conn->connection->socket, &tmp_blob, &sendlen, SOCKET_FLAG_BLOCK);
- if (!NT_STATUS_IS_OK(status) || (req->out.size != sendlen)) {
- smbsrv_terminate_connection(req->smb_conn, "failed to send reply\n");
- return;
- }
+ /* add the request to the list of requests that need to be
+ sent to the client, then mark the socket event structure
+ ready for write events */
+ DLIST_ADD_END(req->smb_conn->pending_send, req, struct smbsrv_request *);
- req_destroy(req);
+ req->smb_conn->connection->event.fde->flags |= EVENT_FD_WRITE;
}
/*
diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c
index 91de20bb31..ff83bfc80c 100644
--- a/source4/smb_server/smb_server.c
+++ b/source4/smb_server/smb_server.c
@@ -804,8 +804,42 @@ static void smbsrv_recv(struct server_connection *conn, time_t t, uint16_t flags
*/
static void smbsrv_send(struct server_connection *conn, time_t t, uint16_t flags)
{
- DEBUG(10,("smbsrv_send\n"));
- return;
+ struct smbsrv_connection *smb_conn = conn->private_data;
+
+ while (smb_conn->pending_send) {
+ struct smbsrv_request *req = smb_conn->pending_send;
+ DATA_BLOB blob;
+ NTSTATUS status;
+ size_t sendlen;
+
+ blob.data = req->out.buffer;
+ blob.length = req->out.size;
+
+ /* send as much of this request as we can */
+ status = socket_send(conn->socket, &blob, &sendlen, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
+ return;
+ }
+ if (sendlen == 0) {
+ break;
+ }
+
+ req->out.buffer += sendlen;
+ req->out.size -= sendlen;
+
+ /* is the whole request gone? */
+ if (req->out.size == 0) {
+ DLIST_REMOVE(smb_conn->pending_send, req);
+ req_destroy(req);
+ }
+ }
+
+ /* if no more requests are pending to be sent then
+ we should stop select for write */
+ if (smb_conn->pending_send == NULL) {
+ conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ }
}
/*
@@ -860,11 +894,9 @@ void smbsrv_accept(struct server_connection *conn)
DEBUG(5,("smbsrv_accept\n"));
- smb_conn = talloc_p(conn, struct smbsrv_connection);
+ smb_conn = talloc_zero_p(conn, struct smbsrv_connection);
if (!smb_conn) return;
- ZERO_STRUCTP(smb_conn);
-
smb_conn->pid = getpid();
sub_set_context(&smb_conn->substitute);
diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h
index 4fdbdfe671..4de2aac907 100644
--- a/source4/smb_server/smb_server.h
+++ b/source4/smb_server/smb_server.h
@@ -74,6 +74,9 @@ struct smbsrv_tcon {
/* the context for a single SMB request. This is passed to any request-context
functions */
struct smbsrv_request {
+ /* the smbsrv_connection needs a list of requests queued for send */
+ struct smbsrv_request *next, *prev;
+
/* the server_context contains all context specific to this SMB socket */
struct smbsrv_connection *smb_conn;
@@ -289,4 +292,8 @@ struct smbsrv_connection {
/* this holds a partially received request */
struct smbsrv_request *partial_req;
+
+ /* this holds list of replies that are waiting to be sent
+ to the client */
+ struct smbsrv_request *pending_send;
};