summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/async_sock.h51
-rw-r--r--source3/include/includes.h2
-rw-r--r--source3/lib/async_sock.c693
4 files changed, 2 insertions, 746 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 607044fd83..e786a81efa 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -344,7 +344,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \
lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o \
lib/interfaces.o lib/memcache.o \
lib/util_transfer_file.o ../lib/async_req/async_req.o \
- lib/async_sock.o \
+ ../lib/async_req/async_sock.o \
$(TDB_LIB_OBJ) \
$(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/interface.o lib/pidfile.o \
diff --git a/source3/include/async_sock.h b/source3/include/async_sock.h
deleted file mode 100644
index c6f95d64d5..0000000000
--- a/source3/include/async_sock.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- async socket operations
- Copyright (C) Volker Lendecke 2008
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __ASYNC_SOCK_H__
-#define __ASYNC_SOCK_H__
-
-#include "includes.h"
-
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno);
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno);
-int async_syscall_result_int(struct async_req *req, int *perrno);
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, const void *buffer, size_t length,
- int flags);
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, void *buffer, size_t length,
- int flags);
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- int fd, const struct sockaddr *address,
- socklen_t address_len);
-NTSTATUS async_connect_recv(struct async_req *req, int *perrno);
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, const void *buffer, size_t length,
- int flags);
-NTSTATUS sendall_recv(struct async_req *req);
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, void *buffer, size_t length,
- int flags);
-NTSTATUS recvall_recv(struct async_req *req);
-
-#endif
diff --git a/source3/include/includes.h b/source3/include/includes.h
index ea856f1c16..7b0b270f60 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -649,7 +649,7 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
#include "memcache.h"
#include "../lib/async_req/async_req.h"
#include "async_smb.h"
-#include "async_sock.h"
+#include "../lib/async_req/async_sock.h"
#include "services.h"
#include "eventlog.h"
diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c
deleted file mode 100644
index 73ff6f2870..0000000000
--- a/source3/lib/async_sock.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- async socket syscalls
- Copyright (C) Volker Lendecke 2008
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-
-/**
- * Discriminator for async_syscall_state
- */
-enum async_syscall_type {
- ASYNC_SYSCALL_SEND,
- ASYNC_SYSCALL_SENDALL,
- ASYNC_SYSCALL_RECV,
- ASYNC_SYSCALL_RECVALL,
- ASYNC_SYSCALL_CONNECT
-};
-
-/**
- * Holder for syscall arguments and the result
- */
-
-struct async_syscall_state {
- enum async_syscall_type syscall_type;
- struct fd_event *fde;
-
- union {
- struct param_send {
- int fd;
- const void *buffer;
- size_t length;
- int flags;
- } param_send;
- struct param_sendall {
- int fd;
- const void *buffer;
- size_t length;
- int flags;
- size_t sent;
- } param_sendall;
- struct param_recv {
- int fd;
- void *buffer;
- size_t length;
- int flags;
- } param_recv;
- struct param_recvall {
- int fd;
- void *buffer;
- size_t length;
- int flags;
- size_t received;
- } param_recvall;
- struct param_connect {
- /**
- * connect needs to be done on a nonblocking
- * socket. Keep the old flags around
- */
- long old_sockflags;
- int fd;
- const struct sockaddr *address;
- socklen_t address_len;
- } param_connect;
- } param;
-
- union {
- ssize_t result_ssize_t;
- size_t result_size_t;
- int result_int;
- } result;
- int sys_errno;
-};
-
-/**
- * @brief Create a new async syscall req
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state. The async_syscall_state will be put
- * into the async_req as private_data.
- */
-
-static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- enum async_syscall_type type,
- struct async_syscall_state **pstate)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- if (!async_req_setup(mem_ctx, &result, &state,
- struct async_syscall_state)) {
- return NULL;
- }
- state->syscall_type = type;
-
- result->private_data = state;
-
- *pstate = state;
-
- return result;
-}
-
-/**
- * @brief Create a new async syscall req based on a fd
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] fd The file descriptor we work on
- * @param[in] fde_flags EVENT_FD_READ/WRITE -- what are we interested in?
- * @param[in] fde_cb The callback function for the file descriptor event
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state and an associated file descriptor
- * event.
- */
-
-static struct async_req *async_fde_syscall_new(
- TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- enum async_syscall_type type,
- int fd,
- uint16_t fde_flags,
- void (*fde_cb)(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv),
- struct async_syscall_state **pstate)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_syscall_new(mem_ctx, ev, type, &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->fde = event_add_fd(ev, state, fd, fde_flags, fde_cb, result);
- if (state->fde == NULL) {
- TALLOC_FREE(result);
- return NULL;
- }
- *pstate = state;
- return result;
-}
-
-/**
- * Retrieve a ssize_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_ssize_t;
-}
-
-/**
- * Retrieve a size_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_size_t;
-}
-
-/**
- * Retrieve a int typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-int async_syscall_result_int(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_int;
-}
-
-/**
- * fde event handler for the "send" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the send
- * @param[in] flags Can only be EVENT_FD_WRITE here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_send_callback(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_send *p = &state->param.param_send;
-
- if (state->syscall_type != ASYNC_SYSCALL_SEND) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
-}
-
-/**
- * Async version of send(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to send to
- * @param[in] buffer The buffer to send
- * @param[in] length How many bytes to send
- * @param[in] flags flags passed to send(2)
- *
- * This function is a direct counterpart of send(2)
- */
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, const void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_SEND,
- fd, EVENT_FD_WRITE, async_send_callback,
- &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_send.fd = fd;
- state->param.param_send.buffer = buffer;
- state->param.param_send.length = length;
- state->param.param_send.flags = flags;
-
- return result;
-}
-
-/**
- * fde event handler for the "sendall" syscall group
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the send
- * @param[in] flags Can only be EVENT_FD_WRITE here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_sendall_callback(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_sendall *p = &state->param.param_sendall;
-
- if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent,
- p->length - p->sent, p->flags);
- state->sys_errno = errno;
-
- if (state->result.result_ssize_t == -1) {
- async_req_error(req, map_nt_error_from_unix(state->sys_errno));
- return;
- }
-
- if (state->result.result_ssize_t == 0) {
- async_req_error(req, NT_STATUS_END_OF_FILE);
- return;
- }
-
- p->sent += state->result.result_ssize_t;
- if (p->sent > p->length) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- if (p->sent == p->length) {
- TALLOC_FREE(state->fde);
- async_req_done(req);
- }
-}
-
-/**
- * @brief Send all bytes to a socket
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to send to
- * @param[in] buffer The buffer to send
- * @param[in] length How many bytes to send
- * @param[in] flags flags passed to send(2)
- *
- * async_sendall calls send(2) as long as it is necessary to send all of the
- * "length" bytes
- */
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, const void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
- fd, EVENT_FD_WRITE, async_sendall_callback,
- &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_sendall.fd = fd;
- state->param.param_sendall.buffer = buffer;
- state->param.param_sendall.length = length;
- state->param.param_sendall.flags = flags;
- state->param.param_sendall.sent = 0;
-
- return result;
-}
-
-NTSTATUS sendall_recv(struct async_req *req)
-{
- return async_req_simple_recv(req);
-}
-
-/**
- * fde event handler for the "recv" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the recv
- * @param[in] flags Can only be EVENT_FD_READ here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_recv_callback(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_recv *p = &state->param.param_recv;
-
- if (state->syscall_type != ASYNC_SYSCALL_RECV) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
-}
-
-/**
- * Async version of recv(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] buffer The buffer to recv into
- * @param[in] length How many bytes to recv
- * @param[in] flags flags passed to recv(2)
- *
- * This function is a direct counterpart of recv(2)
- */
-
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_RECV,
- fd, EVENT_FD_READ, async_recv_callback,
- &state);
-
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_recv.fd = fd;
- state->param.param_recv.buffer = buffer;
- state->param.param_recv.length = length;
- state->param.param_recv.flags = flags;
-
- return result;
-}
-
-/**
- * fde event handler for the "recvall" syscall group
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the recv
- * @param[in] flags Can only be EVENT_FD_READ here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_recvall_callback(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_recvall *p = &state->param.param_recvall;
-
- if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- state->result.result_ssize_t = recv(p->fd,
- (char *)p->buffer + p->received,
- p->length - p->received, p->flags);
- state->sys_errno = errno;
-
- if (state->result.result_ssize_t == -1) {
- async_req_error(req, map_nt_error_from_unix(state->sys_errno));
- return;
- }
-
- if (state->result.result_ssize_t == 0) {
- async_req_error(req, NT_STATUS_END_OF_FILE);
- return;
- }
-
- p->received += state->result.result_ssize_t;
- if (p->received > p->length) {
- async_req_error(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
-
- if (p->received == p->length) {
- TALLOC_FREE(state->fde);
- async_req_done(req);
- }
-}
-
-/**
- * Receive a specified number of bytes from a socket
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] buffer The buffer to recv into
- * @param[in] length How many bytes to recv
- * @param[in] flags flags passed to recv(2)
- *
- * async_recvall will call recv(2) until "length" bytes are received
- */
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- int fd, void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
- fd, EVENT_FD_READ, async_recvall_callback,
- &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_recvall.fd = fd;
- state->param.param_recvall.buffer = buffer;
- state->param.param_recvall.length = length;
- state->param.param_recvall.flags = flags;
- state->param.param_recvall.received = 0;
-
- return result;
-}
-
-NTSTATUS recvall_recv(struct async_req *req)
-{
- return async_req_simple_recv(req);
-}
-
-struct async_connect_state {
- int fd;
- int result;
- int sys_errno;
- long old_sockflags;
-};
-
-static void async_connect_connected(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv);
-
-/**
- * @brief async version of connect(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] address Where to connect?
- * @param[in] address_len Length of *address
- * @retval The async request
- *
- * This function sets the socket into non-blocking state to be able to call
- * connect in an async state. This will be reset when the request is finished.
- */
-
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- int fd, const struct sockaddr *address,
- socklen_t address_len)
-{
- struct async_req *result;
- struct async_connect_state *state;
- struct fd_event *fde;
- NTSTATUS status;
-
- if (!async_req_setup(mem_ctx, &result, &state,
- struct async_connect_state)) {
- return NULL;
- }
-
- /**
- * We have to set the socket to nonblocking for async connect(2). Keep
- * the old sockflags around.
- */
-
- state->fd = fd;
- state->sys_errno = 0;
-
- state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0);
- if (state->old_sockflags == -1) {
- goto post_errno;
- }
-
- set_blocking(fd, false);
-
- state->result = connect(fd, address, address_len);
- if (state->result == 0) {
- state->sys_errno = 0;
- status = NT_STATUS_OK;
- goto post_status;
- }
-
- /**
- * A number of error messages show that something good is progressing
- * and that we have to wait for readability.
- *
- * If none of them are present, bail out.
- */
-
- if (!(errno == EINPROGRESS || errno == EALREADY ||
-#ifdef EISCONN
- errno == EISCONN ||
-#endif
- errno == EAGAIN || errno == EINTR)) {
- goto post_errno;
- }
-
- fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE,
- async_connect_connected, result);
- if (fde == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto post_status;
- }
- return result;
-
- post_errno:
- state->sys_errno = errno;
- status = map_nt_error_from_unix(state->sys_errno);
- post_status:
- sys_fcntl_long(fd, F_SETFL, state->old_sockflags);
- if (!async_post_status(result, ev, status)) {
- goto fail;
- }
- return result;
- fail:
- TALLOC_FREE(result);
- return NULL;
-}
-
-/**
- * fde event handler for connect(2)
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the connect
- * @param[in] flags Indicate read/writeability of the socket
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_connect_connected(struct event_context *ev,
- struct fd_event *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_connect_state *state = talloc_get_type_abort(
- req->private_data, struct async_connect_state);
-
- TALLOC_FREE(fde);
-
- /*
- * Stevens, Network Programming says that if there's a
- * successful connect, the socket is only writable. Upon an
- * error, it's both readable and writable.
- */
- if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE))
- == (EVENT_FD_READ|EVENT_FD_WRITE)) {
- int sockerr;
- socklen_t err_len = sizeof(sockerr);
-
- if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
- (void *)&sockerr, &err_len) == 0) {
- errno = sockerr;
- }
-
- state->sys_errno = errno;
-
- DEBUG(10, ("connect returned %s\n", strerror(errno)));
-
- sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
- async_req_error(req, map_nt_error_from_unix(state->sys_errno));
- return;
- }
-
- state->sys_errno = 0;
- async_req_done(req);
-}
-
-NTSTATUS async_connect_recv(struct async_req *req, int *perrno)
-{
- struct async_connect_state *state = talloc_get_type_abort(
- req->private_data, struct async_connect_state);
- NTSTATUS status;
-
- sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
-
- *perrno = state->sys_errno;
-
- if (async_req_is_error(req, &status)) {
- return status;
- }
- if (state->sys_errno == 0) {
- return NT_STATUS_OK;
- }
- return map_nt_error_from_unix(state->sys_errno);
-}