summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-02-18 09:23:32 +0100
committerStefan Metzmacher <metze@samba.org>2009-03-19 16:25:53 +0100
commitccfd6a6e39ab999df0eba0d9e94cc22f1aa6e000 (patch)
treee8170af680958b1ed170bd4a476073649cd06f6d
parent6c88d61bdd7333c671f440ada23bca7169cd60fc (diff)
downloadsamba-ccfd6a6e39ab999df0eba0d9e94cc22f1aa6e000.tar.gz
samba-ccfd6a6e39ab999df0eba0d9e94cc22f1aa6e000.tar.bz2
samba-ccfd6a6e39ab999df0eba0d9e94cc22f1aa6e000.zip
lib/tsocket: add tsocket_recvfrom_send/recv()
metze
-rw-r--r--lib/tsocket/config.mk3
-rw-r--r--lib/tsocket/tsocket.h13
-rw-r--r--lib/tsocket/tsocket_recvfrom.c164
3 files changed, 178 insertions, 2 deletions
diff --git a/lib/tsocket/config.mk b/lib/tsocket/config.mk
index 016663ffea..18cb8260e0 100644
--- a/lib/tsocket/config.mk
+++ b/lib/tsocket/config.mk
@@ -4,7 +4,8 @@ PRIVATE_DEPENDENCIES = LIBTALLOC LIBTEVENT LIBREPLACE_NETWORK
LIBTSOCKET_OBJ_FILES = $(addprefix ../lib/tsocket/, \
tsocket.o \
tsocket_helpers.o \
- tsocket_bsd.o)
+ tsocket_bsd.o \
+ tsocket_recvfrom.o)
PUBLIC_HEADERS += $(addprefix ../lib/tsocket/, \
tsocket.h\
diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h
index 04eb989a07..8cabd4263f 100644
--- a/lib/tsocket/tsocket.h
+++ b/lib/tsocket/tsocket.h
@@ -124,7 +124,6 @@ int _tsocket_address_create_socket(const struct tsocket_address *addr,
* BSD sockets: inet, inet6 and unix
*/
-
int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
const char *fam,
const char *addr,
@@ -161,5 +160,17 @@ int _tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
_tsocket_context_bsd_wrap_existing(mem_ctx, fd, cod, _sock, \
__location__)
+/*
+ * Async helpers
+ */
+
+struct tevent_req *tsocket_recvfrom_send(struct tsocket_context *sock,
+ TALLOC_CTX *mem_ctx);
+ssize_t tsocket_recvfrom_recv(struct tevent_req *req,
+ int *perrno,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **buf,
+ struct tsocket_address **src);
+
#endif /* _TSOCKET_H */
diff --git a/lib/tsocket/tsocket_recvfrom.c b/lib/tsocket/tsocket_recvfrom.c
new file mode 100644
index 0000000000..467738cfc2
--- /dev/null
+++ b/lib/tsocket/tsocket_recvfrom.c
@@ -0,0 +1,164 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ ** NOTE! The following LGPL license applies to the tevent
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+#include "tsocket.h"
+#include "tsocket_internal.h"
+
+struct tsocket_recvfrom_state {
+ /* this structs are owned by the caller */
+ struct {
+ struct tsocket_context *sock;
+ } caller;
+
+ uint8_t *buf;
+ size_t len;
+ struct tsocket_address *src;
+};
+
+static int tsocket_recvfrom_state_destructor(struct tsocket_recvfrom_state *state)
+{
+ if (state->caller.sock) {
+ tsocket_set_readable_handler(state->caller.sock, NULL, NULL);
+ }
+ ZERO_STRUCT(state->caller);
+
+ return 0;
+}
+
+static void tsocket_recvfrom_handler(struct tsocket_context *sock,
+ void *private_data);
+
+struct tevent_req *tsocket_recvfrom_send(struct tsocket_context *sock,
+ TALLOC_CTX *mem_ctx)
+{
+ struct tevent_req *req;
+ struct tsocket_recvfrom_state *state;
+ int ret;
+ int err;
+ bool dummy;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct tsocket_recvfrom_state);
+ if (!req) {
+ return NULL;
+ }
+
+ state->caller.sock = sock;
+ state->buf = NULL;
+ state->len = 0;
+ state->src = NULL;
+
+ talloc_set_destructor(state, tsocket_recvfrom_state_destructor);
+
+ ret = tsocket_set_readable_handler(sock,
+ tsocket_recvfrom_handler,
+ req);
+ err = tsocket_error_from_errno(ret, errno, &dummy);
+ if (tevent_req_error(req, err)) {
+ goto post;
+ }
+
+ return req;
+
+ post:
+ return tevent_req_post(req, sock->event.ctx);
+}
+
+static void tsocket_recvfrom_handler(struct tsocket_context *sock,
+ void *private_data)
+{
+ struct tevent_req *req = talloc_get_type(private_data,
+ struct tevent_req);
+ struct tsocket_recvfrom_state *state = tevent_req_data(req,
+ struct tsocket_recvfrom_state);
+ ssize_t ret;
+ int err;
+ bool retry;
+
+ ret = tsocket_pending(state->caller.sock);
+ if (ret == 0) {
+ /* retry later */
+ return;
+ }
+ err = tsocket_error_from_errno(ret, errno, &retry);
+ if (retry) {
+ /* retry later */
+ return;
+ }
+ if (tevent_req_error(req, err)) {
+ return;
+ }
+
+ state->buf = talloc_array(state, uint8_t, ret);
+ if (tevent_req_nomem(state->buf, req)) {
+ return;
+ }
+ state->len = ret;
+
+ ret = tsocket_recvfrom(state->caller.sock,
+ state->buf,
+ state->len,
+ state,
+ &state->src);
+ err = tsocket_error_from_errno(ret, errno, &retry);
+ if (retry) {
+ /* retry later */
+ return;
+ }
+ if (tevent_req_error(req, err)) {
+ return;
+ }
+
+ if (ret != state->len) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+ssize_t tsocket_recvfrom_recv(struct tevent_req *req,
+ int *perrno,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **buf,
+ struct tsocket_address **src)
+{
+ struct tsocket_recvfrom_state *state = tevent_req_data(req,
+ struct tsocket_recvfrom_state);
+ ssize_t ret;
+
+ ret = tsocket_simple_int_recv(req, perrno);
+ if (ret == 0) {
+ *buf = talloc_move(mem_ctx, &state->buf);
+ ret = state->len;
+ if (src) {
+ *src = talloc_move(mem_ctx, &state->src);
+ }
+ }
+
+ tevent_req_received(req);
+ return ret;
+}
+