Add read_pkt_send/recv
authorVolker Lendecke <vl@samba.org>
Tue, 10 Feb 2009 16:29:02 +0000 (17:29 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 10 Feb 2009 17:29:34 +0000 (18:29 +0100)
source3/include/proto.h
source3/lib/util.c

index c2391c7550b64cfd036f9beb22ab756b91e905ae..fd6ccce3e04a8df687ef9b2d7d3f086c674cedfc 100644 (file)
@@ -1242,6 +1242,15 @@ bool is_valid_policy_hnd(const POLICY_HND *hnd);
 bool policy_hnd_equal(const struct policy_handle *hnd1,
                      const struct policy_handle *hnd2);
 const char *strip_hostname(const char *s);
+struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx,
+                               struct event_context *ev,
+                               int fd, size_t initial,
+                               ssize_t (*more)(uint8_t *buf, size_t buflen,
+                                               void *priv),
+                               void *priv);
+ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
+                     uint8_t **pbuf, int *perr);
+
 
 /* The following definitions come from lib/util_file.c  */
 
index df01c0306f9e7a5c57ec6d6e1c873ba6d43cbfdf..68d332243610d5308c4c314a66c1350797383ebb 100644 (file)
@@ -3234,3 +3234,102 @@ const char *strip_hostname(const char *s)
 
        return s;
 }
+
+struct read_pkt_state {
+       struct event_context *ev;
+       int fd;
+       uint8_t *buf;
+       ssize_t (*more)(uint8_t *buf, size_t buflen, void *priv);
+       void *priv;
+};
+
+static void read_pkt_done(struct async_req *subreq);
+
+struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx,
+                               struct event_context *ev,
+                               int fd, size_t initial,
+                               ssize_t (*more)(uint8_t *buf, size_t buflen,
+                                               void *priv),
+                               void *priv)
+{
+       struct async_req *result, *subreq;
+       struct read_pkt_state *state;
+
+       if (!async_req_setup(mem_ctx, &result, &state,
+                            struct read_pkt_state)) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->fd = fd;
+       state->more = more;
+
+       state->buf = talloc_array(state, uint8_t, initial);
+       if (state->buf == NULL) {
+               goto fail;
+       }
+       subreq = recvall_send(state, ev, fd, state->buf, initial, 0);
+       if (subreq == NULL) {
+               goto fail;
+       }
+       subreq->async.fn = read_pkt_done;
+       subreq->async.priv = result;
+       return result;
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
+
+static void read_pkt_done(struct async_req *subreq)
+{
+       struct async_req *req = talloc_get_type_abort(
+               subreq->async.priv, struct async_req);
+       struct read_pkt_state *state = talloc_get_type_abort(
+               req->private_data, struct read_pkt_state);
+       size_t current_size;
+       ssize_t received;
+       ssize_t more;
+       int err;
+
+       received = recvall_recv(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (received == -1) {
+               async_req_error(req, err);
+               return;
+       }
+       current_size = talloc_get_size(state->buf);
+
+       more = state->more(state->buf, current_size, state->priv);
+       if (more < 0) {
+               async_req_error(req, EIO);
+               return;
+       }
+       if (more == 0) {
+               async_req_done(req);
+               return;
+       }
+       state->buf = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t,
+                                         current_size + more);
+       if (async_req_nomem(state->buf, req)) {
+               return;
+       }
+       subreq = recvall_send(state, state->ev, state->fd,
+                             state->buf + current_size, more, 0);
+       if (async_req_nomem(subreq, req)) {
+               return;
+       }
+       subreq->async.fn = read_pkt_done;
+       subreq->async.priv = req;
+}
+
+ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
+                     uint8_t **pbuf, int *perr)
+{
+       struct read_pkt_state *state = talloc_get_type_abort(
+               req->private_data, struct read_pkt_state);
+
+       if (async_req_is_errno(req, perr)) {
+               return -1;
+       }
+       *pbuf = talloc_move(mem_ctx, &state->buf);
+       return talloc_get_size(*pbuf);
+}