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/>.
25 #include "system/filesys.h"
27 #include "tsocket_internal.h"
29 int tsocket_simple_int_recv(struct tevent_req *req, int *perrno)
31 enum tevent_req_state state;
34 if (!tevent_req_is_error(req, &state, &error)) {
39 case TEVENT_REQ_NO_MEMORY:
42 case TEVENT_REQ_TIMED_OUT:
45 case TEVENT_REQ_USER_ERROR:
56 struct tsocket_address *_tsocket_address_create(TALLOC_CTX *mem_ctx,
57 const struct tsocket_address_ops *ops,
63 void **ppstate = (void **)pstate;
64 struct tsocket_address *addr;
66 addr = talloc_zero(mem_ctx, struct tsocket_address);
71 addr->location = location;
72 addr->private_data = talloc_size(addr, psize);
73 if (!addr->private_data) {
77 talloc_set_name_const(addr->private_data, type);
79 *ppstate = addr->private_data;
83 char *tsocket_address_string(const struct tsocket_address *addr,
87 return talloc_strdup(mem_ctx, "NULL");
89 return addr->ops->string(addr, mem_ctx);
92 struct tsocket_address *_tsocket_address_copy(const struct tsocket_address *addr,
96 return addr->ops->copy(addr, mem_ctx, location);
99 struct tdgram_context {
100 const char *location;
101 const struct tdgram_context_ops *ops;
104 struct tevent_req *recvfrom_req;
105 struct tevent_req *sendto_req;
108 static int tdgram_context_destructor(struct tdgram_context *dgram)
110 if (dgram->recvfrom_req) {
111 tevent_req_received(dgram->recvfrom_req);
114 if (dgram->sendto_req) {
115 tevent_req_received(dgram->sendto_req);
121 struct tdgram_context *_tdgram_context_create(TALLOC_CTX *mem_ctx,
122 const struct tdgram_context_ops *ops,
126 const char *location)
128 struct tdgram_context *dgram;
129 void **ppstate = (void **)pstate;
132 dgram = talloc(mem_ctx, struct tdgram_context);
136 dgram->location = location;
138 dgram->recvfrom_req = NULL;
139 dgram->sendto_req = NULL;
141 state = talloc_size(dgram, psize);
146 talloc_set_name_const(state, type);
148 dgram->private_data = state;
150 talloc_set_destructor(dgram, tdgram_context_destructor);
156 void *_tdgram_context_data(struct tdgram_context *dgram)
158 return dgram->private_data;
161 struct tdgram_recvfrom_state {
162 const struct tdgram_context_ops *ops;
163 struct tdgram_context *dgram;
166 struct tsocket_address *src;
169 static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state *state)
172 state->dgram->recvfrom_req = NULL;
178 static void tdgram_recvfrom_done(struct tevent_req *subreq);
180 struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
181 struct tevent_context *ev,
182 struct tdgram_context *dgram)
184 struct tevent_req *req;
185 struct tdgram_recvfrom_state *state;
186 struct tevent_req *subreq;
188 req = tevent_req_create(mem_ctx, &state,
189 struct tdgram_recvfrom_state);
194 state->ops = dgram->ops;
195 state->dgram = dgram;
200 if (dgram->recvfrom_req) {
201 tevent_req_error(req, EBUSY);
204 dgram->recvfrom_req = req;
206 talloc_set_destructor(state, tdgram_recvfrom_destructor);
208 subreq = state->ops->recvfrom_send(state, ev, dgram);
209 if (tevent_req_nomem(subreq, req)) {
212 tevent_req_set_callback(subreq, tdgram_recvfrom_done, req);
217 tevent_req_post(req, ev);
221 static void tdgram_recvfrom_done(struct tevent_req *subreq)
223 struct tevent_req *req = tevent_req_callback_data(subreq,
225 struct tdgram_recvfrom_state *state = tevent_req_data(req,
226 struct tdgram_recvfrom_state);
230 ret = state->ops->recvfrom_recv(subreq, &sys_errno, state,
231 &state->buf, &state->src);
233 tevent_req_error(req, sys_errno);
239 tevent_req_done(req);
242 ssize_t tdgram_recvfrom_recv(struct tevent_req *req,
246 struct tsocket_address **src)
248 struct tdgram_recvfrom_state *state = tevent_req_data(req,
249 struct tdgram_recvfrom_state);
252 ret = tsocket_simple_int_recv(req, perrno);
254 *buf = talloc_move(mem_ctx, &state->buf);
257 *src = talloc_move(mem_ctx, &state->src);
261 tevent_req_received(req);
265 struct tdgram_sendto_state {
266 const struct tdgram_context_ops *ops;
267 struct tdgram_context *dgram;
271 static int tdgram_sendto_destructor(struct tdgram_sendto_state *state)
274 state->dgram->sendto_req = NULL;
280 static void tdgram_sendto_done(struct tevent_req *subreq);
282 struct tevent_req *tdgram_sendto_send(TALLOC_CTX *mem_ctx,
283 struct tevent_context *ev,
284 struct tdgram_context *dgram,
285 const uint8_t *buf, size_t len,
286 const struct tsocket_address *dst)
288 struct tevent_req *req;
289 struct tdgram_sendto_state *state;
290 struct tevent_req *subreq;
292 req = tevent_req_create(mem_ctx, &state,
293 struct tdgram_sendto_state);
298 state->ops = dgram->ops;
299 state->dgram = dgram;
303 tevent_req_error(req, EINVAL);
307 if (dgram->sendto_req) {
308 tevent_req_error(req, EBUSY);
311 dgram->sendto_req = req;
313 talloc_set_destructor(state, tdgram_sendto_destructor);
315 subreq = state->ops->sendto_send(state, ev, dgram,
317 if (tevent_req_nomem(subreq, req)) {
320 tevent_req_set_callback(subreq, tdgram_sendto_done, req);
325 tevent_req_post(req, ev);
329 static void tdgram_sendto_done(struct tevent_req *subreq)
331 struct tevent_req *req = tevent_req_callback_data(subreq,
333 struct tdgram_sendto_state *state = tevent_req_data(req,
334 struct tdgram_sendto_state);
338 ret = state->ops->sendto_recv(subreq, &sys_errno);
340 tevent_req_error(req, sys_errno);
346 tevent_req_done(req);
349 ssize_t tdgram_sendto_recv(struct tevent_req *req,
352 struct tdgram_sendto_state *state = tevent_req_data(req,
353 struct tdgram_sendto_state);
356 ret = tsocket_simple_int_recv(req, perrno);
361 tevent_req_received(req);
365 struct tdgram_disconnect_state {
366 const struct tdgram_context_ops *ops;
369 static void tdgram_disconnect_done(struct tevent_req *subreq);
371 struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
372 struct tevent_context *ev,
373 struct tdgram_context *dgram)
375 struct tevent_req *req;
376 struct tdgram_disconnect_state *state;
377 struct tevent_req *subreq;
379 req = tevent_req_create(mem_ctx, &state,
380 struct tdgram_disconnect_state);
385 state->ops = dgram->ops;
387 if (dgram->recvfrom_req || dgram->sendto_req) {
388 tevent_req_error(req, EBUSY);
392 subreq = state->ops->disconnect_send(state, ev, dgram);
393 if (tevent_req_nomem(subreq, req)) {
396 tevent_req_set_callback(subreq, tdgram_disconnect_done, req);
401 tevent_req_post(req, ev);
405 static void tdgram_disconnect_done(struct tevent_req *subreq)
407 struct tevent_req *req = tevent_req_callback_data(subreq,
409 struct tdgram_disconnect_state *state = tevent_req_data(req,
410 struct tdgram_disconnect_state);
414 ret = state->ops->disconnect_recv(subreq, &sys_errno);
416 tevent_req_error(req, sys_errno);
420 tevent_req_done(req);
423 int tdgram_disconnect_recv(struct tevent_req *req,
428 ret = tsocket_simple_int_recv(req, perrno);
430 tevent_req_received(req);
434 struct tstream_context {
435 const char *location;
436 const struct tstream_context_ops *ops;
439 struct tevent_req *readv_req;
440 struct tevent_req *writev_req;
443 static int tstream_context_destructor(struct tstream_context *stream)
445 if (stream->readv_req) {
446 tevent_req_received(stream->readv_req);
449 if (stream->writev_req) {
450 tevent_req_received(stream->writev_req);
456 struct tstream_context *_tstream_context_create(TALLOC_CTX *mem_ctx,
457 const struct tstream_context_ops *ops,
461 const char *location)
463 struct tstream_context *stream;
464 void **ppstate = (void **)pstate;
467 stream = talloc(mem_ctx, struct tstream_context);
468 if (stream == NULL) {
471 stream->location = location;
473 stream->readv_req = NULL;
474 stream->writev_req = NULL;
476 state = talloc_size(stream, psize);
481 talloc_set_name_const(state, type);
483 stream->private_data = state;
485 talloc_set_destructor(stream, tstream_context_destructor);
491 void *_tstream_context_data(struct tstream_context *stream)
493 return stream->private_data;
496 ssize_t tstream_pending_bytes(struct tstream_context *stream)
498 return stream->ops->pending_bytes(stream);
501 struct tstream_readv_state {
502 const struct tstream_context_ops *ops;
503 struct tstream_context *stream;
507 static int tstream_readv_destructor(struct tstream_readv_state *state)
510 state->stream->readv_req = NULL;
516 static void tstream_readv_done(struct tevent_req *subreq);
518 struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
519 struct tevent_context *ev,
520 struct tstream_context *stream,
521 struct iovec *vector,
524 struct tevent_req *req;
525 struct tstream_readv_state *state;
526 struct tevent_req *subreq;
530 req = tevent_req_create(mem_ctx, &state,
531 struct tstream_readv_state);
536 state->ops = stream->ops;
537 state->stream = stream;
540 /* first check if the input is ok */
542 if (count > IOV_MAX) {
543 tevent_req_error(req, EMSGSIZE);
548 for (i=0; i < count; i++) {
550 tmp += vector[i].iov_len;
553 tevent_req_error(req, EMSGSIZE);
561 tevent_req_error(req, EINVAL);
565 if (stream->readv_req) {
566 tevent_req_error(req, EBUSY);
569 stream->readv_req = req;
571 talloc_set_destructor(state, tstream_readv_destructor);
573 subreq = state->ops->readv_send(state, ev, stream, vector, count);
574 if (tevent_req_nomem(subreq, req)) {
577 tevent_req_set_callback(subreq, tstream_readv_done, req);
582 tevent_req_post(req, ev);
586 static void tstream_readv_done(struct tevent_req *subreq)
588 struct tevent_req *req = tevent_req_callback_data(subreq,
590 struct tstream_readv_state *state = tevent_req_data(req,
591 struct tstream_readv_state);
595 ret = state->ops->readv_recv(subreq, &sys_errno);
598 tevent_req_error(req, sys_errno);
604 tevent_req_done(req);
607 int tstream_readv_recv(struct tevent_req *req,
610 struct tstream_readv_state *state = tevent_req_data(req,
611 struct tstream_readv_state);
614 ret = tsocket_simple_int_recv(req, perrno);
619 tevent_req_received(req);
623 struct tstream_writev_state {
624 const struct tstream_context_ops *ops;
625 struct tstream_context *stream;
629 static int tstream_writev_destructor(struct tstream_writev_state *state)
632 state->stream->writev_req = NULL;
638 static void tstream_writev_done(struct tevent_req *subreq);
640 struct tevent_req *tstream_writev_send(TALLOC_CTX *mem_ctx,
641 struct tevent_context *ev,
642 struct tstream_context *stream,
643 const struct iovec *vector,
646 struct tevent_req *req;
647 struct tstream_writev_state *state;
648 struct tevent_req *subreq;
652 req = tevent_req_create(mem_ctx, &state,
653 struct tstream_writev_state);
658 state->ops = stream->ops;
659 state->stream = stream;
662 /* first check if the input is ok */
664 if (count > IOV_MAX) {
665 tevent_req_error(req, EMSGSIZE);
670 for (i=0; i < count; i++) {
672 tmp += vector[i].iov_len;
674 if (tmp < to_write) {
675 tevent_req_error(req, EMSGSIZE);
683 tevent_req_error(req, EINVAL);
687 if (stream->writev_req) {
688 tevent_req_error(req, EBUSY);
691 stream->writev_req = req;
693 talloc_set_destructor(state, tstream_writev_destructor);
695 subreq = state->ops->writev_send(state, ev, stream, vector, count);
696 if (tevent_req_nomem(subreq, req)) {
699 tevent_req_set_callback(subreq, tstream_writev_done, req);
704 tevent_req_post(req, ev);
708 static void tstream_writev_done(struct tevent_req *subreq)
710 struct tevent_req *req = tevent_req_callback_data(subreq,
712 struct tstream_writev_state *state = tevent_req_data(req,
713 struct tstream_writev_state);
717 ret = state->ops->writev_recv(subreq, &sys_errno);
719 tevent_req_error(req, sys_errno);
725 tevent_req_done(req);
728 int tstream_writev_recv(struct tevent_req *req,
731 struct tstream_writev_state *state = tevent_req_data(req,
732 struct tstream_writev_state);
735 ret = tsocket_simple_int_recv(req, perrno);
740 tevent_req_received(req);
744 struct tstream_disconnect_state {
745 const struct tstream_context_ops *ops;
748 static void tstream_disconnect_done(struct tevent_req *subreq);
750 struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
751 struct tevent_context *ev,
752 struct tstream_context *stream)
754 struct tevent_req *req;
755 struct tstream_disconnect_state *state;
756 struct tevent_req *subreq;
758 req = tevent_req_create(mem_ctx, &state,
759 struct tstream_disconnect_state);
764 state->ops = stream->ops;
766 if (stream->readv_req || stream->writev_req) {
767 tevent_req_error(req, EBUSY);
771 subreq = state->ops->disconnect_send(state, ev, stream);
772 if (tevent_req_nomem(subreq, req)) {
775 tevent_req_set_callback(subreq, tstream_disconnect_done, req);
780 tevent_req_post(req, ev);
784 static void tstream_disconnect_done(struct tevent_req *subreq)
786 struct tevent_req *req = tevent_req_callback_data(subreq,
788 struct tstream_disconnect_state *state = tevent_req_data(req,
789 struct tstream_disconnect_state);
793 ret = state->ops->disconnect_recv(subreq, &sys_errno);
795 tevent_req_error(req, sys_errno);
799 tevent_req_done(req);
802 int tstream_disconnect_recv(struct tevent_req *req,
807 ret = tsocket_simple_int_recv(req, perrno);
809 tevent_req_received(req);