summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-01-04 01:45:06 +0100
committerVolker Lendecke <vl@samba.org>2009-01-04 16:42:40 +0100
commit0cc63c64166d2e26b7a7ffc0e78ea6041de35f53 (patch)
tree17f0df0946f9fee6b45bf95ac4dafc3974036109
parent19b783cce9edf7b616cd1a9d9dcb78a02791d89e (diff)
downloadsamba-0cc63c64166d2e26b7a7ffc0e78ea6041de35f53.tar.gz
samba-0cc63c64166d2e26b7a7ffc0e78ea6041de35f53.tar.bz2
samba-0cc63c64166d2e26b7a7ffc0e78ea6041de35f53.zip
Add open_socket_out_defer_send/recv
-rw-r--r--source3/include/proto.h7
-rw-r--r--source3/lib/util_sock.c111
2 files changed, 118 insertions, 0 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 957302c378..6238ba3d00 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1465,6 +1465,13 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
uint16_t port,
int timeout);
NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd);
+struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct timeval wait_time,
+ const struct sockaddr_storage *pss,
+ uint16_t port,
+ int timeout);
+NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd);
bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,
int timeout, int *fd_index, int *fd);
int open_udp_socket(const char *host, int port);
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 3356318c88..518bb78f65 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -1152,6 +1152,117 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
return status;
}
+struct open_socket_out_defer_state {
+ struct event_context *ev;
+ struct sockaddr_storage ss;
+ uint16_t port;
+ int timeout;
+ int fd;
+};
+
+static void open_socket_out_defer_waited(struct async_req *subreq);
+static void open_socket_out_defer_connected(struct async_req *subreq);
+
+struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct timeval wait_time,
+ const struct sockaddr_storage *pss,
+ uint16_t port,
+ int timeout)
+{
+ struct async_req *result, *subreq;
+ struct open_socket_out_defer_state *state;
+ NTSTATUS status;
+
+ result = async_req_new(mem_ctx);
+ if (result == NULL) {
+ return NULL;
+ }
+ state = talloc(result, struct open_socket_out_defer_state);
+ if (state == NULL) {
+ goto fail;
+ }
+ result->private_data = state;
+
+ state->ev = ev;
+ state->ss = *pss;
+ state->port = port;
+ state->timeout = timeout;
+
+ subreq = async_wait_send(state, ev, wait_time);
+ if (subreq == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto post_status;
+ }
+ subreq->async.fn = open_socket_out_defer_waited;
+ subreq->async.priv = result;
+ return result;
+
+ post_status:
+ if (!async_post_status(result, ev, status)) {
+ goto fail;
+ }
+ return result;
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void open_socket_out_defer_waited(struct async_req *subreq)
+{
+ struct async_req *req = talloc_get_type_abort(
+ subreq->async.priv, struct async_req);
+ struct open_socket_out_defer_state *state = talloc_get_type_abort(
+ req->private_data, struct open_socket_out_defer_state);
+ NTSTATUS status;
+
+ status = async_wait_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(req, status);
+ return;
+ }
+
+ subreq = open_socket_out_send(state, state->ev, &state->ss,
+ state->port, state->timeout);
+ if (async_req_nomem(subreq, req)) {
+ return;
+ }
+ subreq->async.fn = open_socket_out_defer_connected;
+ subreq->async.priv = req;
+}
+
+static void open_socket_out_defer_connected(struct async_req *subreq)
+{
+ struct async_req *req = talloc_get_type_abort(
+ subreq->async.priv, struct async_req);
+ struct open_socket_out_defer_state *state = talloc_get_type_abort(
+ req->private_data, struct open_socket_out_defer_state);
+ NTSTATUS status;
+
+ status = open_socket_out_recv(subreq, &state->fd);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(req, status);
+ return;
+ }
+ async_req_done(req);
+}
+
+NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd)
+{
+ struct open_socket_out_defer_state *state = talloc_get_type_abort(
+ req->private_data, struct open_socket_out_defer_state);
+ NTSTATUS status;
+
+ if (async_req_is_error(req, &status)) {
+ return status;
+ }
+ *pfd = state->fd;
+ state->fd = -1;
+ return NT_STATUS_OK;
+}
+
/*******************************************************************
Create an outgoing TCP socket to the first addr that connects.