summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2011-07-26 19:44:51 +0200
committerVolker Lendecke <vlendec@samba.org>2011-07-27 00:47:45 +0200
commit1335059ff5ef1a8f0f9aedf6a6db366074d457f3 (patch)
tree34ef11e4eb14bc67c9dbe66f3ca16e427e4062e9 /source3/libsmb
parenta5ba41881c393d075238a537aeca273df446389b (diff)
downloadsamba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.tar.gz
samba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.tar.bz2
samba-1335059ff5ef1a8f0f9aedf6a6db366074d457f3.zip
s3: Fix async smb handling
In cli_echo with more than one response we ended up with more than one read_smb request. One from the call to cli_smb_req_set_pending called from cli_smb_received. The other one from cli_smb_received itself. I don't really see another way to deal with this than to hold the read_smb request in the cli_state. Metze, please check! Volker
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/async_smb.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index 87614bd326..ecc77803b0 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -139,6 +139,7 @@ void cli_smb_req_unset_pending(struct tevent_req *req)
* delete the socket read fde.
*/
TALLOC_FREE(cli->conn.pending);
+ cli->conn.read_smb_req = NULL;
return;
}
@@ -193,7 +194,6 @@ bool cli_smb_req_set_pending(struct tevent_req *req)
struct cli_state *cli;
struct tevent_req **pending;
int num_pending;
- struct tevent_req *subreq;
cli = state->cli;
num_pending = talloc_array_length(cli->conn.pending);
@@ -207,7 +207,7 @@ bool cli_smb_req_set_pending(struct tevent_req *req)
cli->conn.pending = pending;
talloc_set_destructor(req, cli_smb_req_destructor);
- if (num_pending > 0) {
+ if (cli->conn.read_smb_req != NULL) {
return true;
}
@@ -215,12 +215,13 @@ bool cli_smb_req_set_pending(struct tevent_req *req)
* We're the first ones, add the read_smb request that waits for the
* answer from the server
*/
- subreq = read_smb_send(cli->conn.pending, state->ev, cli->conn.fd);
- if (subreq == NULL) {
+ cli->conn.read_smb_req = read_smb_send(cli->conn.pending, state->ev,
+ cli->conn.fd);
+ if (cli->conn.read_smb_req == NULL) {
cli_smb_req_unset_pending(req);
return false;
}
- tevent_req_set_callback(subreq, cli_smb_received, cli);
+ tevent_req_set_callback(cli->conn.read_smb_req, cli_smb_received, cli);
return true;
}
@@ -531,8 +532,16 @@ static void cli_smb_received(struct tevent_req *subreq)
uint16_t mid;
bool oplock_break;
+ if (subreq != cli->conn.read_smb_req) {
+ DEBUG(1, ("Internal error: cli_smb_received called with "
+ "unexpected subreq\n"));
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto fail;
+ }
+
received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err);
TALLOC_FREE(subreq);
+ cli->conn.read_smb_req = NULL;
if (received == -1) {
cli_state_disconnect(cli);
status = map_nt_error_from_unix(err);
@@ -642,19 +651,22 @@ static void cli_smb_received(struct tevent_req *subreq)
TALLOC_FREE(chain);
}
done:
- if (talloc_array_length(cli->conn.pending) > 0) {
+ if ((talloc_array_length(cli->conn.pending) > 0) &&
+ (cli->conn.read_smb_req == NULL)) {
/*
* Set up another read request for the other pending cli_smb
* requests
*/
state = tevent_req_data(cli->conn.pending[0],
struct cli_smb_state);
- subreq = read_smb_send(cli->conn.pending, state->ev, cli->conn.fd);
- if (subreq == NULL) {
+ cli->conn.read_smb_req = read_smb_send(
+ cli->conn.pending, state->ev, cli->conn.fd);
+ if (cli->conn.read_smb_req == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
- tevent_req_set_callback(subreq, cli_smb_received, cli);
+ tevent_req_set_callback(cli->conn.read_smb_req,
+ cli_smb_received, cli);
}
return;
fail: