struct req_read_state {
struct winbindd_request *wb_req;
size_t max_extra_data;
+ ssize_t ret;
};
-bool async_req_is_wbcerr(struct async_req *req, wbcErr *pwbc_err)
-{
- enum async_req_state state;
- uint64_t error;
- if (!async_req_is_error(req, &state, &error)) {
- *pwbc_err = WBC_ERR_SUCCESS;
- return false;
- }
-
- switch (state) {
- case ASYNC_REQ_USER_ERROR:
- *pwbc_err = error;
- break;
- case ASYNC_REQ_TIMED_OUT:
- *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
- break;
- case ASYNC_REQ_NO_MEMORY:
- *pwbc_err = WBC_ERR_NO_MEMORY;
- break;
- default:
- *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
- break;
- }
- return true;
-}
-
-wbcErr map_wbc_err_from_errno(int error)
-{
- switch(error) {
- case EPERM:
- case EACCES:
- return WBC_ERR_AUTH_ERROR;
- case ENOMEM:
- return WBC_ERR_NO_MEMORY;
- case EIO:
- default:
- return WBC_ERR_UNKNOWN_FAILURE;
- }
-}
-
-wbcErr async_req_simple_recv_wbcerr(struct async_req *req)
-{
- wbcErr wbc_err;
-
- if (async_req_is_wbcerr(req, &wbc_err)) {
- return wbc_err;
- }
-
- return WBC_ERR_SUCCESS;
-}
-
static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
static void wb_req_read_done(struct tevent_req *subreq);
-struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int fd, size_t max_extra_data)
+struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, size_t max_extra_data)
{
- struct async_req *result;
- struct tevent_req *subreq;
+ struct tevent_req *req, *subreq;
struct req_read_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct req_read_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct req_read_state);
+ if (req == NULL) {
return NULL;
}
state->max_extra_data = max_extra_data;
subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
- if (subreq == NULL) {
- goto nomem;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
-
- subreq->async.fn = wb_req_read_done;
- subreq->async.private_data = result;
- return result;
- nomem:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, wb_req_read_done, req);
+ return req;
}
static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
static void wb_req_read_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.private_data, struct async_req);
- struct req_read_state *state = talloc_get_type_abort(
- req->private_data, struct req_read_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct req_read_state *state = tevent_req_data(
+ req, struct req_read_state);
int err;
- ssize_t ret;
uint8_t *buf;
- ret = read_packet_recv(subreq, state, &buf, &err);
+ state->ret = read_packet_recv(subreq, state, &buf, &err);
TALLOC_FREE(subreq);
- if (ret == -1) {
- async_req_error(req, map_wbc_err_from_errno(err));
+ if (state->ret == -1) {
+ tevent_req_error(req, err);
return;
}
} else {
state->wb_req->extra_data.data = NULL;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_request **preq)
+ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_request **preq, int *err)
{
- struct req_read_state *state = talloc_get_type_abort(
- req->private_data, struct req_read_state);
- wbcErr wbc_err;
+ struct req_read_state *state = tevent_req_data(
+ req, struct req_read_state);
- if (async_req_is_wbcerr(req, &wbc_err)) {
- return wbc_err;
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
}
*preq = talloc_move(mem_ctx, &state->wb_req);
- return WBC_ERR_SUCCESS;
+ return state->ret;
}
struct req_write_state {
struct iovec iov[2];
+ ssize_t ret;
};
static void wb_req_write_done(struct tevent_req *subreq);
-struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd,
- struct winbindd_request *wb_req)
+struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req)
{
- struct async_req *result;
- struct tevent_req *subreq;
+ struct tevent_req *req, *subreq;
struct req_write_state *state;
int count = 1;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct req_write_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct req_write_state);
+ if (req == NULL) {
return NULL;
}
count = 2;
}
- subreq = writev_send(state, ev, fd, state->iov, count);
- if (subreq == NULL) {
- goto fail;
+ subreq = writev_send(state, ev, queue, fd, state->iov, count);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = wb_req_write_done;
- subreq->async.private_data = result;
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, wb_req_write_done, req);
+ return req;
}
static void wb_req_write_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.private_data, struct async_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct req_write_state *state = tevent_req_data(
+ req, struct req_write_state);
int err;
- ssize_t ret;
- ret = writev_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (ret < 0) {
- async_req_error(req, map_wbc_err_from_errno(err));
+ state->ret = writev_recv(subreq, &err);
+ /*
+ * We do not TALLOC_FREE(subreq) here, as this would trigger the next
+ * write of a client. The winbind protocol is purely request/response
+ * without multiplex ID's, so having multiple requeusts on the fly
+ * would confuse sequencing.
+ *
+ * Eventually the writev_req will be freed, "subreq" a child of "req"
+ */
+ if (state->ret < 0) {
+ tevent_req_error(req, err);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-wbcErr wb_req_write_recv(struct async_req *req)
+ssize_t wb_req_write_recv(struct tevent_req *req, int *err)
{
- return async_req_simple_recv_wbcerr(req);
+ struct req_write_state *state = tevent_req_data(
+ req, struct req_write_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ return state->ret;
}
struct resp_read_state {
struct winbindd_response *wb_resp;
+ ssize_t ret;
};
static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
static void wb_resp_read_done(struct tevent_req *subreq);
-struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd)
+struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev, int fd)
{
- struct async_req *result;
- struct tevent_req *subreq;
+ struct tevent_req *req, *subreq;
struct resp_read_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct resp_read_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct resp_read_state);
+ if (req == NULL) {
return NULL;
}
subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
- if (subreq == NULL) {
- goto nomem;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = wb_resp_read_done;
- subreq->async.private_data = result;
- return result;
-
- nomem:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, wb_resp_read_done, req);
+ return req;
}
static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
return -1;
}
}
- return resp->length - 4;
+ return resp->length - buflen;
}
static void wb_resp_read_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.private_data, struct async_req);
- struct resp_read_state *state = talloc_get_type_abort(
- req->private_data, struct resp_read_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct resp_read_state *state = tevent_req_data(
+ req, struct resp_read_state);
uint8_t *buf;
int err;
- ssize_t ret;
- ret = read_packet_recv(subreq, state, &buf, &err);
+ state->ret = read_packet_recv(subreq, state, &buf, &err);
TALLOC_FREE(subreq);
- if (ret == -1) {
- async_req_error(req, map_wbc_err_from_errno(err));
+ if (state->ret == -1) {
+ tevent_req_error(req, err);
return;
}
} else {
state->wb_resp->extra_data.data = NULL;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_response **presp)
+ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presp, int *err)
{
- struct resp_read_state *state = talloc_get_type_abort(
- req->private_data, struct resp_read_state);
- wbcErr wbc_err;
+ struct resp_read_state *state = tevent_req_data(
+ req, struct resp_read_state);
- if (async_req_is_wbcerr(req, &wbc_err)) {
- return wbc_err;
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
}
*presp = talloc_move(mem_ctx, &state->wb_resp);
- return WBC_ERR_SUCCESS;
+ return state->ret;
}
struct resp_write_state {
struct iovec iov[2];
+ ssize_t ret;
};
static void wb_resp_write_done(struct tevent_req *subreq);
-struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd,
- struct winbindd_response *wb_resp)
+struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_response *wb_resp)
{
- struct async_req *result;
- struct tevent_req *subreq;
+ struct tevent_req *req, *subreq;
struct resp_write_state *state;
int count = 1;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct resp_write_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
+ if (req == NULL) {
return NULL;
}
count = 2;
}
- subreq = writev_send(state, ev, fd, state->iov, count);
- if (subreq == NULL) {
- goto fail;
+ subreq = writev_send(state, ev, queue, fd, state->iov, count);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = wb_resp_write_done;
- subreq->async.private_data = result;
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, wb_resp_write_done, req);
+ return req;
}
static void wb_resp_write_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.private_data, struct async_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct resp_write_state *state = tevent_req_data(
+ req, struct resp_write_state);
int err;
- ssize_t ret;
- ret = writev_recv(subreq, &err);
+ state->ret = writev_recv(subreq, &err);
TALLOC_FREE(subreq);
- if (ret < 0) {
- async_req_error(req, map_wbc_err_from_errno(err));
+ if (state->ret < 0) {
+ tevent_req_error(req, err);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-wbcErr wb_resp_write_recv(struct async_req *req)
+ssize_t wb_resp_write_recv(struct tevent_req *req, int *err)
{
- return async_req_simple_recv_wbcerr(req);
+ struct resp_write_state *state = tevent_req_data(
+ req, struct resp_write_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ return state->ret;
+}
+
+static bool closed_fd(int fd)
+{
+ struct timeval tv;
+ fd_set r_fds;
+
+ if (fd == -1) {
+ return true;
+ }
+
+ FD_ZERO(&r_fds);
+ FD_SET(fd, &r_fds);
+ ZERO_STRUCT(tv);
+
+ if ((select(fd+1, &r_fds, NULL, NULL, &tv) == -1)
+ || FD_ISSET(fd, &r_fds)) {
+ return true;
+ }
+
+ return false;
+}
+
+struct wb_simple_trans_state {
+ struct tevent_context *ev;
+ int fd;
+ struct winbindd_response *wb_resp;
+};
+
+static void wb_simple_trans_write_done(struct tevent_req *subreq);
+static void wb_simple_trans_read_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_simple_trans_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (closed_fd(fd)) {
+ tevent_req_error(req, EPIPE);
+ return tevent_req_post(req, ev);
+ }
+
+ wb_req->length = sizeof(struct winbindd_request);
+
+ state->ev = ev;
+ state->fd = fd;
+
+ subreq = wb_req_write_send(state, ev, queue, fd, wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_simple_trans_write_done, req);
+
+ return req;
+}
+
+static void wb_simple_trans_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+ ssize_t ret;
+ int err;
+
+ ret = wb_req_write_recv(subreq, &err);
+ /*
+ * We do not TALLOC_FREE(subreq) here, as this would trigger the next
+ * write of a client. The winbind protocol is purely request/response
+ * without multiplex ID's, so having multiple requeusts on the fly
+ * would confuse sequencing.
+ *
+ * Eventually the "subreq" will be freed, it is a child of "req"
+ */
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+ subreq = wb_resp_read_send(state, state->ev, state->fd);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_simple_trans_read_done, req);
+}
+
+static void wb_simple_trans_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+ ssize_t ret;
+ int err;
+
+ ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse, int *err)
+{
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ *presponse = talloc_move(mem_ctx, &state->wb_resp);
+ return 0;
}