[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha6-182-gab63bad

Kai Blin kai at samba.org
Wed Jan 28 10:36:33 GMT 2009


The branch, master has been updated
       via  ab63bad94bfc378aca08d3314692de90e1aa1bf3 (commit)
      from  c2a2006f8a8fdb8941158fc121ce551604cd1bae (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ab63bad94bfc378aca08d3314692de90e1aa1bf3
Author: Kai Blin <kai at samba.org>
Date:   Sat Jan 24 10:00:13 2009 +0100

    async_sock: Move to top level

-----------------------------------------------------------------------

Summary of changes:
 lib/async_req/async_sock.c   |  703 ++++++++++++++++++++++++++++++++++++++++++
 lib/async_req/async_sock.h   |   51 +++
 lib/async_req/config.mk      |    2 +-
 source3/Makefile.in          |    2 +-
 source3/include/async_sock.h |   51 ---
 source3/include/includes.h   |    2 +-
 source3/lib/async_sock.c     |  693 -----------------------------------------
 7 files changed, 757 insertions(+), 747 deletions(-)
 create mode 100644 lib/async_req/async_sock.c
 create mode 100644 lib/async_req/async_sock.h
 delete mode 100644 source3/include/async_sock.h
 delete mode 100644 source3/lib/async_sock.c


Changeset truncated at 500 lines:

diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
new file mode 100644
index 0000000..7febc54
--- /dev/null
+++ b/lib/async_req/async_sock.c
@@ -0,0 +1,703 @@
+/*
+   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"
+#include "lib/talloc/talloc.h"
+#include "lib/tevent/tevent.h"
+#include "lib/async_req/async_req.h"
+#include "lib/async_req/async_sock.h"
+#include <fcntl.h>
+
+#ifndef TALLOC_FREE
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+#endif
+
+/**
+ * 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 tevent_fd *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 tevent_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 TEVENT_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 tevent_context *ev,
+	enum async_syscall_type type,
+	int fd,
+	uint16_t fde_flags,
+	void (*fde_cb)(struct tevent_context *ev,
+		       struct tevent_fd *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 = tevent_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 TEVENT_FD_WRITE here
+ * @param[in] priv	private data, "struct async_req *" in this case
+ */
+
+static void async_send_callback(struct tevent_context *ev,
+				struct tevent_fd *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 tevent_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, TEVENT_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 TEVENT_FD_WRITE here
+ * @param[in] priv	private data, "struct async_req *" in this case
+ */
+
+static void async_sendall_callback(struct tevent_context *ev,
+				   struct tevent_fd *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,
+					    (const 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 tevent_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, TEVENT_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 TEVENT_FD_READ here
+ * @param[in] priv	private data, "struct async_req *" in this case
+ */
+
+static void async_recv_callback(struct tevent_context *ev,
+				struct tevent_fd *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 tevent_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, TEVENT_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 TEVENT_FD_READ here
+ * @param[in] priv	private data, "struct async_req *" in this case
+ */
+
+static void async_recvall_callback(struct tevent_context *ev,
+				   struct tevent_fd *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) {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list