summaryrefslogtreecommitdiff
path: root/source3/smbd/process.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-10-30 16:22:24 -0700
committerJeremy Allison <jra@samba.org>2007-10-30 16:22:24 -0700
commitc3250149e12338fac5093991b385ad2807c92d1f (patch)
treefa1e5387fb10d02b1f09da59fc20d7a8520e65fc /source3/smbd/process.c
parent4367f4b4d4ce075f3fe8e88e68dbda47e2252349 (diff)
downloadsamba-c3250149e12338fac5093991b385ad2807c92d1f.tar.gz
samba-c3250149e12338fac5093991b385ad2807c92d1f.tar.bz2
samba-c3250149e12338fac5093991b385ad2807c92d1f.zip
Add new parameter, "min receivefile size" (by default set
to zero). If non-zero, writeX calls greater than this value will be left in the socket buffer for later handling with recvfile (or userspace equivalent). Definition of recvfile for your system is left as an exercise for the reader (I'm working on getting splice working :-). Jeremy. (This used to be commit 11c03b75ddbcb6e36b231bb40a1773d1c550621c)
Diffstat (limited to 'source3/smbd/process.c')
-rw-r--r--source3/smbd/process.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index ed1bf762e9..1c8d8a6e76 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -25,7 +25,7 @@ extern int smb_echo_count;
const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
-/*
+/*
* Size of data we can send to client. Set
* by the client for all protocols above CORE.
* Set by us for CORE protocol.
@@ -48,7 +48,9 @@ extern int max_send;
* Initialize a struct smb_request from an inbuf
*/
-void init_smb_request(struct smb_request *req, const uint8 *inbuf)
+void init_smb_request(struct smb_request *req,
+ const uint8 *inbuf,
+ size_t unread_bytes)
{
size_t req_size = smb_len(inbuf) + 4;
/* Ensure we have at least smb_size bytes. */
@@ -63,6 +65,8 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf)
req->vuid = SVAL(inbuf, smb_uid);
req->tid = SVAL(inbuf, smb_tid);
req->wct = CVAL(inbuf, smb_wct);
+ req->unread_bytes = unread_bytes;
+
/* Ensure we have at least wct words and 2 bytes of bcc. */
if (smb_size + req->wct*2 > req_size) {
DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
@@ -231,6 +235,14 @@ bool push_deferred_smb_message(struct smb_request *req,
{
struct timeval end_time;
+ if (req->unread_bytes) {
+ DEBUG(0,("push_deferred_smb_message: logic error ! "
+ "unread_bytes = %u\n",
+ (unsigned int)req->unread_bytes ));
+ smb_panic("push_deferred_smb_message: "
+ "logic error unread_bytes != 0" );
+ }
+
end_time = timeval_sum(&request_time, &timeout);
DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
@@ -382,8 +394,11 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds)
The timeout is in milliseconds
****************************************************************************/
-static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
- size_t *buffer_len, int timeout)
+static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
+ char **buffer,
+ size_t *buffer_len,
+ int timeout,
+ size_t *p_unread)
{
fd_set r_fds, w_fds;
int selrtn;
@@ -391,6 +406,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
int maxfd = 0;
ssize_t len;
+ *p_unread = 0;
smb_read_error = 0;
again:
@@ -565,7 +581,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
goto again;
}
- len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0);
+ len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread);
if (len == -1) {
return False;
@@ -1115,7 +1131,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
Construct a reply to the incoming packet.
****************************************************************************/
-static void construct_reply(char *inbuf, int size)
+static void construct_reply(char *inbuf, int size, size_t unread_bytes)
{
uint8 type = CVAL(inbuf,smb_com);
struct smb_request *req;
@@ -1127,10 +1143,19 @@ static void construct_reply(char *inbuf, int size)
if (!(req = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req, (uint8 *)inbuf);
+ init_smb_request(req, (uint8 *)inbuf, unread_bytes);
switch_message(type, req, size);
+ if (req->unread_bytes) {
+ /* writeX failed. drain socket. */
+ if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
+ req->unread_bytes) {
+ smb_panic("failed to drain pending bytes");
+ }
+ req->unread_bytes = 0;
+ }
+
if (req->outbuf == NULL) {
return;
}
@@ -1152,7 +1177,7 @@ static void construct_reply(char *inbuf, int size)
Process an smb from the client
****************************************************************************/
-static void process_smb(char *inbuf, size_t nread)
+static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
{
static int trans_num;
int msg_type = CVAL(inbuf,0);
@@ -1176,7 +1201,9 @@ static void process_smb(char *inbuf, size_t nread)
DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
smb_len(inbuf) ) );
- DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) );
+ DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
+ (int)nread,
+ (unsigned int)unread_bytes ));
if (msg_type != 0) {
/*
@@ -1188,8 +1215,8 @@ static void process_smb(char *inbuf, size_t nread)
show_msg(inbuf);
- construct_reply(inbuf,nread);
-
+ construct_reply(inbuf,nread,unread_bytes);
+
trans_num++;
}
@@ -1348,7 +1375,7 @@ void chain_reply(struct smb_request *req)
if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req2, (uint8 *)inbuf2);
+ init_smb_request(req2, (uint8 *)inbuf2,0);
/* process the request */
switch_message(smb_com2, req2, new_size);
@@ -1625,6 +1652,7 @@ void smbd_process(void)
{
time_t last_timeout_processing_time = time(NULL);
unsigned int num_smbs = 0;
+ size_t unread_bytes = 0;
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
@@ -1635,8 +1663,8 @@ void smbd_process(void)
size_t inbuf_len;
TALLOC_CTX *frame = talloc_stackframe();
- errno = 0;
-
+ errno = 0;
+
/* Did someone ask for immediate checks on things like blocking locks ? */
if (select_timeout == 0) {
if(!timeout_processing(&select_timeout,
@@ -1648,7 +1676,7 @@ void smbd_process(void)
run_events(smbd_event_context(), 0, NULL, NULL);
while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
- select_timeout)) {
+ select_timeout, &unread_bytes)) {
if(!timeout_processing(&select_timeout,
&last_timeout_processing_time))
return;
@@ -1664,10 +1692,10 @@ void smbd_process(void)
* faster than the select timeout, thus starving out the
* essential processing (change notify, blocking locks) that
* the timeout code does. JRA.
- */
+ */
num_echos = smb_echo_count;
- process_smb(inbuf, inbuf_len);
+ process_smb(inbuf, inbuf_len, unread_bytes);
TALLOC_FREE(inbuf);