2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tsocket
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #endif /* HAVE_CONFIG_H */
28 #include <atalk/tsocket.h>
29 #include "tsocket_internal.h"
31 int tsocket_simple_int_recv(struct tevent_req *req, int *perrno)
33 enum tevent_req_state state;
36 if (!tevent_req_is_error(req, &state, &error)) {
41 case TEVENT_REQ_NO_MEMORY:
44 case TEVENT_REQ_TIMED_OUT:
47 case TEVENT_REQ_USER_ERROR:
59 struct tsocket_address *_tsocket_address_create(TALLOC_CTX *mem_ctx,
60 const struct tsocket_address_ops *ops,
66 void **ppstate = (void **)pstate;
67 struct tsocket_address *addr;
69 addr = talloc_zero(mem_ctx, struct tsocket_address);
74 addr->location = location;
75 addr->private_data = talloc_size(addr, psize);
76 if (!addr->private_data) {
80 talloc_set_name_const(addr->private_data, type);
82 *ppstate = addr->private_data;
86 char *tsocket_address_string(const struct tsocket_address *addr,
90 return talloc_strdup(mem_ctx, "NULL");
92 return addr->ops->string(addr, mem_ctx);
95 struct tsocket_address *_tsocket_address_copy(const struct tsocket_address *addr,
99 return addr->ops->copy(addr, mem_ctx, location);
102 struct tdgram_context {
103 const char *location;
104 const struct tdgram_context_ops *ops;
107 struct tevent_req *recvfrom_req;
108 struct tevent_req *sendto_req;
111 static int tdgram_context_destructor(struct tdgram_context *dgram)
113 if (dgram->recvfrom_req) {
114 tevent_req_received(dgram->recvfrom_req);
117 if (dgram->sendto_req) {
118 tevent_req_received(dgram->sendto_req);
124 struct tdgram_context *_tdgram_context_create(TALLOC_CTX *mem_ctx,
125 const struct tdgram_context_ops *ops,
129 const char *location)
131 struct tdgram_context *dgram;
132 void **ppstate = (void **)pstate;
135 dgram = talloc(mem_ctx, struct tdgram_context);
139 dgram->location = location;
141 dgram->recvfrom_req = NULL;
142 dgram->sendto_req = NULL;
144 state = talloc_size(dgram, psize);
149 talloc_set_name_const(state, type);
151 dgram->private_data = state;
153 talloc_set_destructor(dgram, tdgram_context_destructor);
159 void *_tdgram_context_data(struct tdgram_context *dgram)
161 return dgram->private_data;
164 struct tdgram_recvfrom_state {
165 const struct tdgram_context_ops *ops;
166 struct tdgram_context *dgram;
169 struct tsocket_address *src;
172 static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state *state)
175 state->dgram->recvfrom_req = NULL;
181 static void tdgram_recvfrom_done(struct tevent_req *subreq);
183 struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
184 struct tevent_context *ev,
185 struct tdgram_context *dgram)
187 struct tevent_req *req;
188 struct tdgram_recvfrom_state *state;
189 struct tevent_req *subreq;
191 req = tevent_req_create(mem_ctx, &state,
192 struct tdgram_recvfrom_state);
197 state->ops = dgram->ops;
198 state->dgram = dgram;
203 if (dgram->recvfrom_req) {
204 tevent_req_error(req, EBUSY);
207 dgram->recvfrom_req = req;
209 talloc_set_destructor(state, tdgram_recvfrom_destructor);
211 subreq = state->ops->recvfrom_send(state, ev, dgram);
212 if (tevent_req_nomem(subreq, req)) {
215 tevent_req_set_callback(subreq, tdgram_recvfrom_done, req);
220 tevent_req_post(req, ev);
224 static void tdgram_recvfrom_done(struct tevent_req *subreq)
226 struct tevent_req *req = tevent_req_callback_data(subreq,
228 struct tdgram_recvfrom_state *state = tevent_req_data(req,
229 struct tdgram_recvfrom_state);
233 ret = state->ops->recvfrom_recv(subreq, &sys_errno, state,
234 &state->buf, &state->src);
236 tevent_req_error(req, sys_errno);
242 tevent_req_done(req);
245 ssize_t tdgram_recvfrom_recv(struct tevent_req *req,
249 struct tsocket_address **src)
251 struct tdgram_recvfrom_state *state = tevent_req_data(req,
252 struct tdgram_recvfrom_state);
255 ret = tsocket_simple_int_recv(req, perrno);
257 *buf = talloc_move(mem_ctx, &state->buf);
260 *src = talloc_move(mem_ctx, &state->src);
264 tevent_req_received(req);
268 struct tdgram_sendto_state {
269 const struct tdgram_context_ops *ops;
270 struct tdgram_context *dgram;
274 static int tdgram_sendto_destructor(struct tdgram_sendto_state *state)
277 state->dgram->sendto_req = NULL;
283 static void tdgram_sendto_done(struct tevent_req *subreq);
285 struct tevent_req *tdgram_sendto_send(TALLOC_CTX *mem_ctx,
286 struct tevent_context *ev,
287 struct tdgram_context *dgram,
288 const uint8_t *buf, size_t len,
289 const struct tsocket_address *dst)
291 struct tevent_req *req;
292 struct tdgram_sendto_state *state;
293 struct tevent_req *subreq;
295 req = tevent_req_create(mem_ctx, &state,
296 struct tdgram_sendto_state);
301 state->ops = dgram->ops;
302 state->dgram = dgram;
306 tevent_req_error(req, EINVAL);
310 if (dgram->sendto_req) {
311 tevent_req_error(req, EBUSY);
314 dgram->sendto_req = req;
316 talloc_set_destructor(state, tdgram_sendto_destructor);
318 subreq = state->ops->sendto_send(state, ev, dgram,
320 if (tevent_req_nomem(subreq, req)) {
323 tevent_req_set_callback(subreq, tdgram_sendto_done, req);
328 tevent_req_post(req, ev);
332 static void tdgram_sendto_done(struct tevent_req *subreq)
334 struct tevent_req *req = tevent_req_callback_data(subreq,
336 struct tdgram_sendto_state *state = tevent_req_data(req,
337 struct tdgram_sendto_state);
341 ret = state->ops->sendto_recv(subreq, &sys_errno);
343 tevent_req_error(req, sys_errno);
349 tevent_req_done(req);
352 ssize_t tdgram_sendto_recv(struct tevent_req *req,
355 struct tdgram_sendto_state *state = tevent_req_data(req,
356 struct tdgram_sendto_state);
359 ret = tsocket_simple_int_recv(req, perrno);
364 tevent_req_received(req);
368 struct tdgram_disconnect_state {
369 const struct tdgram_context_ops *ops;
372 static void tdgram_disconnect_done(struct tevent_req *subreq);
374 struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
375 struct tevent_context *ev,
376 struct tdgram_context *dgram)
378 struct tevent_req *req;
379 struct tdgram_disconnect_state *state;
380 struct tevent_req *subreq;
382 req = tevent_req_create(mem_ctx, &state,
383 struct tdgram_disconnect_state);
388 state->ops = dgram->ops;
390 if (dgram->recvfrom_req || dgram->sendto_req) {
391 tevent_req_error(req, EBUSY);
395 subreq = state->ops->disconnect_send(state, ev, dgram);
396 if (tevent_req_nomem(subreq, req)) {
399 tevent_req_set_callback(subreq, tdgram_disconnect_done, req);
404 tevent_req_post(req, ev);
408 static void tdgram_disconnect_done(struct tevent_req *subreq)
410 struct tevent_req *req = tevent_req_callback_data(subreq,
412 struct tdgram_disconnect_state *state = tevent_req_data(req,
413 struct tdgram_disconnect_state);
417 ret = state->ops->disconnect_recv(subreq, &sys_errno);
419 tevent_req_error(req, sys_errno);
423 tevent_req_done(req);
426 int tdgram_disconnect_recv(struct tevent_req *req,
431 ret = tsocket_simple_int_recv(req, perrno);
433 tevent_req_received(req);
437 struct tstream_context {
438 const char *location;
439 const struct tstream_context_ops *ops;
442 struct tevent_req *readv_req;
443 struct tevent_req *writev_req;
446 static int tstream_context_destructor(struct tstream_context *stream)
448 if (stream->readv_req) {
449 tevent_req_received(stream->readv_req);
452 if (stream->writev_req) {
453 tevent_req_received(stream->writev_req);
459 struct tstream_context *_tstream_context_create(TALLOC_CTX *mem_ctx,
460 const struct tstream_context_ops *ops,
464 const char *location)
466 struct tstream_context *stream;
467 void **ppstate = (void **)pstate;
470 stream = talloc(mem_ctx, struct tstream_context);
471 if (stream == NULL) {
474 stream->location = location;
476 stream->readv_req = NULL;
477 stream->writev_req = NULL;
479 state = talloc_size(stream, psize);
484 talloc_set_name_const(state, type);
486 stream->private_data = state;
488 talloc_set_destructor(stream, tstream_context_destructor);
494 void *_tstream_context_data(struct tstream_context *stream)
496 return stream->private_data;
499 ssize_t tstream_pending_bytes(struct tstream_context *stream)
501 return stream->ops->pending_bytes(stream);
504 struct tstream_readv_state {
505 const struct tstream_context_ops *ops;
506 struct tstream_context *stream;
510 static int tstream_readv_destructor(struct tstream_readv_state *state)
513 state->stream->readv_req = NULL;
519 static void tstream_readv_done(struct tevent_req *subreq);
521 struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
522 struct tevent_context *ev,
523 struct tstream_context *stream,
524 struct iovec *vector,
527 struct tevent_req *req;
528 struct tstream_readv_state *state;
529 struct tevent_req *subreq;
533 req = tevent_req_create(mem_ctx, &state,
534 struct tstream_readv_state);
539 state->ops = stream->ops;
540 state->stream = stream;
543 /* first check if the input is ok */
545 if (count > IOV_MAX) {
546 tevent_req_error(req, EMSGSIZE);
551 for (i=0; i < count; i++) {
553 tmp += vector[i].iov_len;
556 tevent_req_error(req, EMSGSIZE);
564 tevent_req_error(req, EINVAL);
568 if (stream->readv_req) {
569 tevent_req_error(req, EBUSY);
572 stream->readv_req = req;
574 talloc_set_destructor(state, tstream_readv_destructor);
576 subreq = state->ops->readv_send(state, ev, stream, vector, count);
577 if (tevent_req_nomem(subreq, req)) {
580 tevent_req_set_callback(subreq, tstream_readv_done, req);
585 tevent_req_post(req, ev);
589 static void tstream_readv_done(struct tevent_req *subreq)
591 struct tevent_req *req = tevent_req_callback_data(subreq,
593 struct tstream_readv_state *state = tevent_req_data(req,
594 struct tstream_readv_state);
598 ret = state->ops->readv_recv(subreq, &sys_errno);
601 tevent_req_error(req, sys_errno);
607 tevent_req_done(req);
610 int tstream_readv_recv(struct tevent_req *req,
613 struct tstream_readv_state *state = tevent_req_data(req,
614 struct tstream_readv_state);
617 ret = tsocket_simple_int_recv(req, perrno);
622 tevent_req_received(req);
626 struct tstream_writev_state {
627 const struct tstream_context_ops *ops;
628 struct tstream_context *stream;
632 static int tstream_writev_destructor(struct tstream_writev_state *state)
635 state->stream->writev_req = NULL;
641 static void tstream_writev_done(struct tevent_req *subreq);
643 struct tevent_req *tstream_writev_send(TALLOC_CTX *mem_ctx,
644 struct tevent_context *ev,
645 struct tstream_context *stream,
646 const struct iovec *vector,
649 struct tevent_req *req;
650 struct tstream_writev_state *state;
651 struct tevent_req *subreq;
655 req = tevent_req_create(mem_ctx, &state,
656 struct tstream_writev_state);
661 state->ops = stream->ops;
662 state->stream = stream;
665 /* first check if the input is ok */
667 if (count > IOV_MAX) {
668 tevent_req_error(req, EMSGSIZE);
673 for (i=0; i < count; i++) {
675 tmp += vector[i].iov_len;
677 if (tmp < to_write) {
678 tevent_req_error(req, EMSGSIZE);
686 tevent_req_error(req, EINVAL);
690 if (stream->writev_req) {
691 tevent_req_error(req, EBUSY);
694 stream->writev_req = req;
696 talloc_set_destructor(state, tstream_writev_destructor);
698 subreq = state->ops->writev_send(state, ev, stream, vector, count);
699 if (tevent_req_nomem(subreq, req)) {
702 tevent_req_set_callback(subreq, tstream_writev_done, req);
707 tevent_req_post(req, ev);
711 static void tstream_writev_done(struct tevent_req *subreq)
713 struct tevent_req *req = tevent_req_callback_data(subreq,
715 struct tstream_writev_state *state = tevent_req_data(req,
716 struct tstream_writev_state);
720 ret = state->ops->writev_recv(subreq, &sys_errno);
722 tevent_req_error(req, sys_errno);
728 tevent_req_done(req);
731 int tstream_writev_recv(struct tevent_req *req,
734 struct tstream_writev_state *state = tevent_req_data(req,
735 struct tstream_writev_state);
738 ret = tsocket_simple_int_recv(req, perrno);
743 tevent_req_received(req);
747 struct tstream_disconnect_state {
748 const struct tstream_context_ops *ops;
751 static void tstream_disconnect_done(struct tevent_req *subreq);
753 struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
754 struct tevent_context *ev,
755 struct tstream_context *stream)
757 struct tevent_req *req;
758 struct tstream_disconnect_state *state;
759 struct tevent_req *subreq;
761 req = tevent_req_create(mem_ctx, &state,
762 struct tstream_disconnect_state);
767 state->ops = stream->ops;
769 if (stream->readv_req || stream->writev_req) {
770 tevent_req_error(req, EBUSY);
774 subreq = state->ops->disconnect_send(state, ev, stream);
775 if (tevent_req_nomem(subreq, req)) {
778 tevent_req_set_callback(subreq, tstream_disconnect_done, req);
783 tevent_req_post(req, ev);
787 static void tstream_disconnect_done(struct tevent_req *subreq)
789 struct tevent_req *req = tevent_req_callback_data(subreq,
791 struct tstream_disconnect_state *state = tevent_req_data(req,
792 struct tstream_disconnect_state);
796 ret = state->ops->disconnect_recv(subreq, &sys_errno);
798 tevent_req_error(req, sys_errno);
802 tevent_req_done(req);
805 int tstream_disconnect_recv(struct tevent_req *req,
810 ret = tsocket_simple_int_recv(req, perrno);
812 tevent_req_received(req);