#include "../lib/util/tevent_ntstatus.h"
#include "rpc_client/rpc_transport.h"
#include "libsmb/cli_np_tstream.h"
+#include "client.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
struct rpc_transport_np_init_state {
struct rpc_cli_transport *transport;
+ int retries;
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ struct timeval abs_timeout;
+ const char *pipe_name;
};
static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq);
{
struct tevent_req *req;
struct rpc_transport_np_init_state *state;
- const char *pipe_name;
struct tevent_req *subreq;
req = tevent_req_create(mem_ctx, &state,
return NULL;
}
- pipe_name = get_pipe_name_from_syntax(state, abstract_syntax);
- if (tevent_req_nomem(pipe_name, req)) {
+ state->ev = ev;
+ state->cli = cli;
+ state->abs_timeout = timeval_current_ofs_msec(cli->timeout);
+ state->pipe_name = get_pipe_name_from_syntax(state, abstract_syntax);
+ if (tevent_req_nomem(state->pipe_name, req)) {
return tevent_req_post(req, ev);
}
- while (pipe_name[0] == '\\') {
- pipe_name++;
+ while (state->pipe_name[0] == '\\') {
+ state->pipe_name++;
}
- subreq = tstream_cli_np_open_send(state, ev, cli, pipe_name);
+ subreq = tstream_cli_np_open_send(state, ev, cli, state->pipe_name);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
return req;
}
+static void rpc_transport_np_init_pipe_open_retry(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval t,
+ void *priv_data)
+{
+ struct tevent_req *subreq;
+ struct tevent_req *req = talloc_get_type(priv_data, struct tevent_req);
+ struct rpc_transport_np_init_state *state = tevent_req_data(
+ req, struct rpc_transport_np_init_state);
+
+ subreq = tstream_cli_np_open_send(state, ev, state->cli,
+ state->pipe_name);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req);
+ state->retries++;
+}
+
static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
status = tstream_cli_np_open_recv(subreq, state, &stream);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_NOT_AVAILABLE)
+ && (!timeval_expired(&state->abs_timeout))) {
+ struct tevent_timer *te;
+ /*
+ * Retry on STATUS_PIPE_NOT_AVAILABLE, Windows starts some
+ * servers (FssagentRpc) on demand.
+ */
+ DEBUG(2, ("RPC pipe %s not available, retry %d\n",
+ state->pipe_name, state->retries));
+ te = tevent_add_timer(state->ev, state,
+ timeval_current_ofs_msec(100 * state->retries),
+ rpc_transport_np_init_pipe_open_retry, req);
+ if (tevent_req_nomem(te, req)) {
+ return;
+ }
+ return;
+ } else if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return;
}