s3: Add async cli_session_request
authorVolker Lendecke <vl@samba.org>
Sun, 12 Dec 2010 17:54:31 +0000 (18:54 +0100)
committerVolker Lendecke <vl@samba.org>
Wed, 22 Dec 2010 16:04:12 +0000 (09:04 -0700)
This does not do the redirects, but I think that might be obsolete anyway

source3/include/async_smb.h
source3/libsmb/async_smb.c

index 7fc4ff7d27976ae90160ff8806e1a5951bb4ac8e..06e69591e1ea721c05f2f926aa6fc91d50d15eb1 100644 (file)
@@ -149,4 +149,11 @@ NTSTATUS cli_pull_error(char *buf);
 
 void cli_set_error(struct cli_state *cli, NTSTATUS status);
 
+struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           int sock,
+                                           const struct nmb_name *called,
+                                           const struct nmb_name *calling);
+bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp);
+
 #endif
index 8db24d202bb4ef1921c85d76b0f853c46ee15813..d7aea7c35d7349b29ca19855e8ca0527cdc88357 100644 (file)
@@ -1231,3 +1231,128 @@ static void cli_state_handler(struct event_context *event_ctx,
                cli->fd = -1;
        }
 }
+
+
+struct cli_session_request_state {
+       struct tevent_context *ev;
+       int sock;
+       uint32 len_hdr;
+       struct iovec iov[3];
+       uint8_t nb_session_response;
+};
+
+static void cli_session_request_sent(struct tevent_req *subreq);
+static void cli_session_request_recvd(struct tevent_req *subreq);
+
+struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           int sock,
+                                           const struct nmb_name *called,
+                                           const struct nmb_name *calling)
+{
+       struct tevent_req *req, *subreq;
+       struct cli_session_request_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct cli_session_request_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->sock = sock;
+
+       state->iov[1].iov_base = name_mangle(
+               state, called->name, called->name_type);
+       if (tevent_req_nomem(state->iov[1].iov_base, req)) {
+               return tevent_req_post(req, ev);
+       }
+       state->iov[1].iov_len = name_len(
+               (char *)state->iov[1].iov_base);
+
+       state->iov[2].iov_base = name_mangle(
+               state, calling->name, calling->name_type);
+       if (tevent_req_nomem(state->iov[2].iov_base, req)) {
+               return tevent_req_post(req, ev);
+       }
+       state->iov[2].iov_len = name_len(
+               (char *)state->iov[2].iov_base);
+
+       _smb_setlen(((char *)&state->len_hdr),
+                   state->iov[1].iov_len + state->iov[2].iov_len);
+       SCVAL((char *)&state->len_hdr, 0, 0x81);
+
+       state->iov[0].iov_base = &state->len_hdr;
+       state->iov[0].iov_len = sizeof(state->len_hdr);
+
+       subreq = writev_send(state, ev, NULL, sock, state->iov, 3);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, cli_session_request_sent, req);
+       return req;
+}
+
+static void cli_session_request_sent(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct cli_session_request_state *state = tevent_req_data(
+               req, struct cli_session_request_state);
+       ssize_t ret;
+       int err;
+
+       ret = writev_recv(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               tevent_req_error(req, err);
+               return;
+       }
+       subreq = read_smb_send(state, state->ev, state->sock);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, cli_session_request_recvd, req);
+}
+
+static void cli_session_request_recvd(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct cli_session_request_state *state = tevent_req_data(
+               req, struct cli_session_request_state);
+       uint8_t *buf;
+       ssize_t ret;
+       int err;
+
+       ret = read_smb_recv(subreq, talloc_tos(), &buf, &err);
+       TALLOC_FREE(subreq);
+
+       if (ret < 4) {
+               ret = -1;
+               err = EIO;
+       }
+       if (ret == -1) {
+               tevent_req_error(req, err);
+               return;
+       }
+       /*
+        * In case of an error there is more information in the data
+        * portion according to RFC1002. We're not subtle enough to
+        * respond to the different error conditions, so drop the
+        * error info here.
+        */
+       state->nb_session_response = CVAL(buf, 0);
+       tevent_req_done(req);
+}
+
+bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp)
+{
+       struct cli_session_request_state *state = tevent_req_data(
+               req, struct cli_session_request_state);
+
+       if (tevent_req_is_unix_error(req, err)) {
+               return false;
+       }
+       *resp = state->nb_session_response;
+       return true;
+}