LCOV - code coverage report
Current view: top level - lib/tsocket - tsocket.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 252 344 73.3 %
Date: 2021-09-23 10:06:22 Functions: 30 33 90.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2009
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the tsocket
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             : 
      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.
      14             : 
      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.
      19             : 
      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/>.
      22             : */
      23             : 
      24             : #include "replace.h"
      25             : #include "system/filesys.h"
      26             : #include "tsocket.h"
      27             : #include "tsocket_internal.h"
      28             : 
      29    39851448 : int tsocket_simple_int_recv(struct tevent_req *req, int *perrno)
      30             : {
      31             :         enum tevent_req_state state;
      32             :         uint64_t error;
      33             : 
      34    39851448 :         if (!tevent_req_is_error(req, &state, &error)) {
      35    39215696 :                 return 0;
      36             :         }
      37             : 
      38      319298 :         switch (state) {
      39           6 :         case TEVENT_REQ_NO_MEMORY:
      40           6 :                 *perrno = ENOMEM;
      41           6 :                 return -1;
      42           0 :         case TEVENT_REQ_TIMED_OUT:
      43           0 :                 *perrno = ETIMEDOUT;
      44           0 :                 return -1;
      45      319292 :         case TEVENT_REQ_USER_ERROR:
      46      319292 :                 *perrno = (int)error;
      47      319292 :                 return -1;
      48           0 :         default:
      49           0 :                 break;
      50             :         }
      51             : 
      52           0 :         *perrno = EIO;
      53           0 :         return -1;
      54             : }
      55             : 
      56      929079 : struct tsocket_address *_tsocket_address_create(TALLOC_CTX *mem_ctx,
      57             :                                                 const struct tsocket_address_ops *ops,
      58             :                                                 void *pstate,
      59             :                                                 size_t psize,
      60             :                                                 const char *type,
      61             :                                                 const char *location)
      62             : {
      63      929079 :         void **ppstate = (void **)pstate;
      64             :         struct tsocket_address *addr;
      65             : 
      66      929079 :         addr = talloc_zero(mem_ctx, struct tsocket_address);
      67      929079 :         if (!addr) {
      68           0 :                 return NULL;
      69             :         }
      70      929079 :         addr->ops = ops;
      71      929079 :         addr->location = location;
      72      929079 :         addr->private_data = talloc_size(addr, psize);
      73      929079 :         if (!addr->private_data) {
      74           0 :                 talloc_free(addr);
      75           0 :                 return NULL;
      76             :         }
      77      929079 :         talloc_set_name_const(addr->private_data, type);
      78             : 
      79      929079 :         *ppstate = addr->private_data;
      80      929079 :         return addr;
      81             : }
      82             : 
      83      636168 : char *tsocket_address_string(const struct tsocket_address *addr,
      84             :                              TALLOC_CTX *mem_ctx)
      85             : {
      86      636168 :         if (!addr) {
      87           0 :                 return talloc_strdup(mem_ctx, "NULL");
      88             :         }
      89      636168 :         return addr->ops->string(addr, mem_ctx);
      90             : }
      91             : 
      92      400717 : struct tsocket_address *_tsocket_address_copy(const struct tsocket_address *addr,
      93             :                                               TALLOC_CTX *mem_ctx,
      94             :                                               const char *location)
      95             : {
      96      400717 :         return addr->ops->copy(addr, mem_ctx, location);
      97             : }
      98             : 
      99             : struct tdgram_context {
     100             :         const char *location;
     101             :         const struct tdgram_context_ops *ops;
     102             :         void *private_data;
     103             : 
     104             :         struct tevent_req *recvfrom_req;
     105             :         struct tevent_req *sendto_req;
     106             : };
     107             : 
     108        6603 : static int tdgram_context_destructor(struct tdgram_context *dgram)
     109             : {
     110        6603 :         if (dgram->recvfrom_req) {
     111           0 :                 tevent_req_received(dgram->recvfrom_req);
     112             :         }
     113             : 
     114        6603 :         if (dgram->sendto_req) {
     115           0 :                 tevent_req_received(dgram->sendto_req);
     116             :         }
     117             : 
     118        6603 :         return 0;
     119             : }
     120             : 
     121        6092 : struct tdgram_context *_tdgram_context_create(TALLOC_CTX *mem_ctx,
     122             :                                         const struct tdgram_context_ops *ops,
     123             :                                         void *pstate,
     124             :                                         size_t psize,
     125             :                                         const char *type,
     126             :                                         const char *location)
     127             : {
     128             :         struct tdgram_context *dgram;
     129        6092 :         void **ppstate = (void **)pstate;
     130             :         void *state;
     131             : 
     132        6092 :         dgram = talloc(mem_ctx, struct tdgram_context);
     133        6092 :         if (dgram == NULL) {
     134           0 :                 return NULL;
     135             :         }
     136        6092 :         dgram->location              = location;
     137        6092 :         dgram->ops           = ops;
     138        6092 :         dgram->recvfrom_req  = NULL;
     139        6092 :         dgram->sendto_req    = NULL;
     140             : 
     141        6092 :         state = talloc_size(dgram, psize);
     142        6092 :         if (state == NULL) {
     143           0 :                 talloc_free(dgram);
     144           0 :                 return NULL;
     145             :         }
     146        6092 :         talloc_set_name_const(state, type);
     147             : 
     148        6092 :         dgram->private_data = state;
     149             : 
     150        6092 :         talloc_set_destructor(dgram, tdgram_context_destructor);
     151             : 
     152        6092 :         *ppstate = state;
     153        6092 :         return dgram;
     154             : }
     155             : 
     156      770395 : void *_tdgram_context_data(struct tdgram_context *dgram)
     157             : {
     158      770395 :         return dgram->private_data;
     159             : }
     160             : 
     161             : struct tdgram_recvfrom_state {
     162             :         const struct tdgram_context_ops *ops;
     163             :         struct tdgram_context *dgram;
     164             :         uint8_t *buf;
     165             :         size_t len;
     166             :         struct tsocket_address *src;
     167             : };
     168             : 
     169      128035 : static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state *state)
     170             : {
     171      128035 :         if (state->dgram) {
     172      128035 :                 state->dgram->recvfrom_req = NULL;
     173             :         }
     174             : 
     175      128035 :         return 0;
     176             : }
     177             : 
     178             : static void tdgram_recvfrom_done(struct tevent_req *subreq);
     179             : 
     180      127524 : struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
     181             :                                         struct tevent_context *ev,
     182             :                                         struct tdgram_context *dgram)
     183             : {
     184             :         struct tevent_req *req;
     185             :         struct tdgram_recvfrom_state *state;
     186             :         struct tevent_req *subreq;
     187             : 
     188      127524 :         req = tevent_req_create(mem_ctx, &state,
     189             :                                 struct tdgram_recvfrom_state);
     190      127524 :         if (req == NULL) {
     191           0 :                 return NULL;
     192             :         }
     193             : 
     194      127524 :         state->ops = dgram->ops;
     195      127524 :         state->dgram = dgram;
     196      127524 :         state->buf = NULL;
     197      127524 :         state->len = 0;
     198      127524 :         state->src = NULL;
     199             : 
     200      127524 :         if (dgram->recvfrom_req) {
     201           0 :                 tevent_req_error(req, EBUSY);
     202           0 :                 goto post;
     203             :         }
     204      127524 :         dgram->recvfrom_req = req;
     205             : 
     206      127524 :         talloc_set_destructor(state, tdgram_recvfrom_destructor);
     207             : 
     208      127524 :         subreq = state->ops->recvfrom_send(state, ev, dgram);
     209      127524 :         if (tevent_req_nomem(subreq, req)) {
     210           0 :                 goto post;
     211             :         }
     212      127524 :         tevent_req_set_callback(subreq, tdgram_recvfrom_done, req);
     213             : 
     214      127524 :         return req;
     215             : 
     216           0 :  post:
     217           0 :         tevent_req_post(req, ev);
     218           0 :         return req;
     219             : }
     220             : 
     221      126115 : static void tdgram_recvfrom_done(struct tevent_req *subreq)
     222             : {
     223      126115 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     224             :                                  struct tevent_req);
     225      126115 :         struct tdgram_recvfrom_state *state = tevent_req_data(req,
     226             :                                               struct tdgram_recvfrom_state);
     227             :         ssize_t ret;
     228             :         int sys_errno;
     229             : 
     230      126115 :         ret = state->ops->recvfrom_recv(subreq, &sys_errno, state,
     231             :                                         &state->buf, &state->src);
     232      126115 :         if (ret == -1) {
     233           6 :                 tevent_req_error(req, sys_errno);
     234           6 :                 return;
     235             :         }
     236             : 
     237      126109 :         state->len = ret;
     238             : 
     239      126109 :         tevent_req_done(req);
     240             : }
     241             : 
     242      126115 : ssize_t tdgram_recvfrom_recv(struct tevent_req *req,
     243             :                              int *perrno,
     244             :                              TALLOC_CTX *mem_ctx,
     245             :                              uint8_t **buf,
     246             :                              struct tsocket_address **src)
     247             : {
     248      126115 :         struct tdgram_recvfrom_state *state = tevent_req_data(req,
     249             :                                               struct tdgram_recvfrom_state);
     250             :         ssize_t ret;
     251             : 
     252      126115 :         ret = tsocket_simple_int_recv(req, perrno);
     253      126115 :         if (ret == 0) {
     254      126109 :                 *buf = talloc_move(mem_ctx, &state->buf);
     255      126109 :                 ret = state->len;
     256      126109 :                 if (src) {
     257      123329 :                         *src = talloc_move(mem_ctx, &state->src);
     258             :                 }
     259             :         }
     260             : 
     261      126115 :         tevent_req_received(req);
     262      126115 :         return ret;
     263             : }
     264             : 
     265             : struct tdgram_sendto_state {
     266             :         const struct tdgram_context_ops *ops;
     267             :         struct tdgram_context *dgram;
     268             :         ssize_t ret;
     269             : };
     270             : 
     271      126537 : static int tdgram_sendto_destructor(struct tdgram_sendto_state *state)
     272             : {
     273      126537 :         if (state->dgram) {
     274      126537 :                 state->dgram->sendto_req = NULL;
     275             :         }
     276             : 
     277      126537 :         return 0;
     278             : }
     279             : 
     280             : static void tdgram_sendto_done(struct tevent_req *subreq);
     281             : 
     282      126537 : 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)
     287             : {
     288             :         struct tevent_req *req;
     289             :         struct tdgram_sendto_state *state;
     290             :         struct tevent_req *subreq;
     291             : 
     292      126537 :         req = tevent_req_create(mem_ctx, &state,
     293             :                                 struct tdgram_sendto_state);
     294      126537 :         if (req == NULL) {
     295           0 :                 return NULL;
     296             :         }
     297             : 
     298      126537 :         state->ops = dgram->ops;
     299      126537 :         state->dgram = dgram;
     300      126537 :         state->ret = -1;
     301             : 
     302      126537 :         if (len == 0) {
     303           0 :                 tevent_req_error(req, EINVAL);
     304           0 :                 goto post;
     305             :         }
     306             : 
     307      126537 :         if (dgram->sendto_req) {
     308           0 :                 tevent_req_error(req, EBUSY);
     309           0 :                 goto post;
     310             :         }
     311      126537 :         dgram->sendto_req = req;
     312             : 
     313      126537 :         talloc_set_destructor(state, tdgram_sendto_destructor);
     314             : 
     315      126537 :         subreq = state->ops->sendto_send(state, ev, dgram,
     316             :                                          buf, len, dst);
     317      126537 :         if (tevent_req_nomem(subreq, req)) {
     318           0 :                 goto post;
     319             :         }
     320      126537 :         tevent_req_set_callback(subreq, tdgram_sendto_done, req);
     321             : 
     322      126537 :         return req;
     323             : 
     324           0 :  post:
     325           0 :         tevent_req_post(req, ev);
     326           0 :         return req;
     327             : }
     328             : 
     329      126537 : static void tdgram_sendto_done(struct tevent_req *subreq)
     330             : {
     331      126537 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     332             :                                  struct tevent_req);
     333      126537 :         struct tdgram_sendto_state *state = tevent_req_data(req,
     334             :                                             struct tdgram_sendto_state);
     335             :         ssize_t ret;
     336             :         int sys_errno;
     337             : 
     338      126537 :         ret = state->ops->sendto_recv(subreq, &sys_errno);
     339      126537 :         if (ret == -1) {
     340          60 :                 tevent_req_error(req, sys_errno);
     341          60 :                 return;
     342             :         }
     343             : 
     344      126477 :         state->ret = ret;
     345             : 
     346      126477 :         tevent_req_done(req);
     347             : }
     348             : 
     349      126537 : ssize_t tdgram_sendto_recv(struct tevent_req *req,
     350             :                            int *perrno)
     351             : {
     352      126537 :         struct tdgram_sendto_state *state = tevent_req_data(req,
     353             :                                             struct tdgram_sendto_state);
     354             :         ssize_t ret;
     355             : 
     356      126537 :         ret = tsocket_simple_int_recv(req, perrno);
     357      126537 :         if (ret == 0) {
     358      126477 :                 ret = state->ret;
     359             :         }
     360             : 
     361      126537 :         tevent_req_received(req);
     362      126537 :         return ret;
     363             : }
     364             : 
     365             : struct tdgram_disconnect_state {
     366             :         const struct tdgram_context_ops *ops;
     367             : };
     368             : 
     369             : static void tdgram_disconnect_done(struct tevent_req *subreq);
     370             : 
     371           0 : struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
     372             :                                           struct tevent_context *ev,
     373             :                                           struct tdgram_context *dgram)
     374             : {
     375             :         struct tevent_req *req;
     376             :         struct tdgram_disconnect_state *state;
     377             :         struct tevent_req *subreq;
     378             : 
     379           0 :         req = tevent_req_create(mem_ctx, &state,
     380             :                                 struct tdgram_disconnect_state);
     381           0 :         if (req == NULL) {
     382           0 :                 return NULL;
     383             :         }
     384             : 
     385           0 :         state->ops = dgram->ops;
     386             : 
     387           0 :         if (dgram->recvfrom_req || dgram->sendto_req) {
     388           0 :                 tevent_req_error(req, EBUSY);
     389           0 :                 goto post;
     390             :         }
     391             : 
     392           0 :         subreq = state->ops->disconnect_send(state, ev, dgram);
     393           0 :         if (tevent_req_nomem(subreq, req)) {
     394           0 :                 goto post;
     395             :         }
     396           0 :         tevent_req_set_callback(subreq, tdgram_disconnect_done, req);
     397             : 
     398           0 :         return req;
     399             : 
     400           0 :  post:
     401           0 :         tevent_req_post(req, ev);
     402           0 :         return req;
     403             : }
     404             : 
     405           0 : static void tdgram_disconnect_done(struct tevent_req *subreq)
     406             : {
     407           0 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     408             :                                  struct tevent_req);
     409           0 :         struct tdgram_disconnect_state *state = tevent_req_data(req,
     410             :                                                 struct tdgram_disconnect_state);
     411             :         int ret;
     412             :         int sys_errno;
     413             : 
     414           0 :         ret = state->ops->disconnect_recv(subreq, &sys_errno);
     415           0 :         if (ret == -1) {
     416           0 :                 tevent_req_error(req, sys_errno);
     417           0 :                 return;
     418             :         }
     419             : 
     420           0 :         tevent_req_done(req);
     421             : }
     422             : 
     423           0 : int tdgram_disconnect_recv(struct tevent_req *req,
     424             :                            int *perrno)
     425             : {
     426             :         int ret;
     427             : 
     428           0 :         ret = tsocket_simple_int_recv(req, perrno);
     429             : 
     430           0 :         tevent_req_received(req);
     431           0 :         return ret;
     432             : }
     433             : 
     434             : struct tstream_context {
     435             :         const char *location;
     436             :         const struct tstream_context_ops *ops;
     437             :         void *private_data;
     438             : 
     439             :         struct tevent_req *readv_req;
     440             :         struct tevent_req *writev_req;
     441             : };
     442             : 
     443      457463 : static int tstream_context_destructor(struct tstream_context *stream)
     444             : {
     445      457463 :         if (stream->readv_req) {
     446           0 :                 tevent_req_received(stream->readv_req);
     447             :         }
     448             : 
     449      457463 :         if (stream->writev_req) {
     450          40 :                 tevent_req_received(stream->writev_req);
     451             :         }
     452             : 
     453      457463 :         return 0;
     454             : }
     455             : 
     456      239602 : struct tstream_context *_tstream_context_create(TALLOC_CTX *mem_ctx,
     457             :                                         const struct tstream_context_ops *ops,
     458             :                                         void *pstate,
     459             :                                         size_t psize,
     460             :                                         const char *type,
     461             :                                         const char *location)
     462             : {
     463             :         struct tstream_context *stream;
     464      239602 :         void **ppstate = (void **)pstate;
     465             :         void *state;
     466             : 
     467      239602 :         stream = talloc(mem_ctx, struct tstream_context);
     468      239602 :         if (stream == NULL) {
     469           0 :                 return NULL;
     470             :         }
     471      239602 :         stream->location     = location;
     472      239602 :         stream->ops          = ops;
     473      239602 :         stream->readv_req    = NULL;
     474      239602 :         stream->writev_req   = NULL;
     475             : 
     476      239602 :         state = talloc_size(stream, psize);
     477      239602 :         if (state == NULL) {
     478           0 :                 talloc_free(stream);
     479           0 :                 return NULL;
     480             :         }
     481      239602 :         talloc_set_name_const(state, type);
     482             : 
     483      239602 :         stream->private_data = state;
     484             : 
     485      239602 :         talloc_set_destructor(stream, tstream_context_destructor);
     486             : 
     487      239602 :         *ppstate = state;
     488      239602 :         return stream;
     489             : }
     490             : 
     491    91512905 : void *_tstream_context_data(struct tstream_context *stream)
     492             : {
     493    91512905 :         return stream->private_data;
     494             : }
     495             : 
     496     1368368 : ssize_t tstream_pending_bytes(struct tstream_context *stream)
     497             : {
     498     1368368 :         return stream->ops->pending_bytes(stream);
     499             : }
     500             : 
     501             : struct tstream_readv_state {
     502             :         const struct tstream_context_ops *ops;
     503             :         struct tstream_context *stream;
     504             :         int ret;
     505             : };
     506             : 
     507    12457640 : static int tstream_readv_destructor(struct tstream_readv_state *state)
     508             : {
     509    12457640 :         if (state->stream) {
     510    12457640 :                 state->stream->readv_req = NULL;
     511             :         }
     512             : 
     513    12457640 :         return 0;
     514             : }
     515             : 
     516             : static void tstream_readv_done(struct tevent_req *subreq);
     517             : 
     518    12454738 : struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
     519             :                                       struct tevent_context *ev,
     520             :                                       struct tstream_context *stream,
     521             :                                       struct iovec *vector,
     522             :                                       size_t count)
     523             : {
     524             :         struct tevent_req *req;
     525             :         struct tstream_readv_state *state;
     526             :         struct tevent_req *subreq;
     527    12454738 :         int to_read = 0;
     528             :         size_t i;
     529             : 
     530    12454738 :         req = tevent_req_create(mem_ctx, &state,
     531             :                                 struct tstream_readv_state);
     532    12454738 :         if (req == NULL) {
     533           0 :                 return NULL;
     534             :         }
     535             : 
     536    12454738 :         state->ops = stream->ops;
     537    12454738 :         state->stream = stream;
     538    12454738 :         state->ret = -1;
     539             : 
     540             :         /* first check if the input is ok */
     541             : #ifdef IOV_MAX
     542    12454738 :         if (count > IOV_MAX) {
     543           0 :                 tevent_req_error(req, EMSGSIZE);
     544           0 :                 goto post;
     545             :         }
     546             : #endif
     547             : 
     548    25511409 :         for (i=0; i < count; i++) {
     549    13140982 :                 int tmp = to_read;
     550    13140982 :                 tmp += vector[i].iov_len;
     551             : 
     552    13140982 :                 if (tmp < to_read) {
     553           0 :                         tevent_req_error(req, EMSGSIZE);
     554           0 :                         goto post;
     555             :                 }
     556             : 
     557    13140982 :                 to_read = tmp;
     558             :         }
     559             : 
     560    12454738 :         if (to_read == 0) {
     561           0 :                 tevent_req_error(req, EINVAL);
     562           0 :                 goto post;
     563             :         }
     564             : 
     565    12454738 :         if (stream->readv_req) {
     566           0 :                 tevent_req_error(req, EBUSY);
     567           0 :                 goto post;
     568             :         }
     569    12454738 :         stream->readv_req = req;
     570             : 
     571    12454738 :         talloc_set_destructor(state, tstream_readv_destructor);
     572             : 
     573    12454738 :         subreq = state->ops->readv_send(state, ev, stream, vector, count);
     574    12454738 :         if (tevent_req_nomem(subreq, req)) {
     575           0 :                 goto post;
     576             :         }
     577    12454738 :         tevent_req_set_callback(subreq, tstream_readv_done, req);
     578             : 
     579    12454738 :         return req;
     580             : 
     581           0 :  post:
     582           0 :         tevent_req_post(req, ev);
     583           0 :         return req;
     584             : }
     585             : 
     586    12437388 : static void tstream_readv_done(struct tevent_req *subreq)
     587             : {
     588    12437388 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     589             :                                  struct tevent_req);
     590    12437388 :         struct tstream_readv_state *state = tevent_req_data(req,
     591             :                                             struct tstream_readv_state);
     592             :         ssize_t ret;
     593             :         int sys_errno;
     594             : 
     595    12437388 :         ret = state->ops->readv_recv(subreq, &sys_errno);
     596    12437388 :         TALLOC_FREE(subreq);
     597    12437388 :         if (ret == -1) {
     598      119601 :                 tevent_req_error(req, sys_errno);
     599      119184 :                 return;
     600             :         }
     601             : 
     602    12317787 :         state->ret = ret;
     603             : 
     604    12317787 :         tevent_req_done(req);
     605             : }
     606             : 
     607    12437388 : int tstream_readv_recv(struct tevent_req *req,
     608             :                        int *perrno)
     609             : {
     610    12437388 :         struct tstream_readv_state *state = tevent_req_data(req,
     611             :                                             struct tstream_readv_state);
     612             :         int ret;
     613             : 
     614    12437388 :         ret = tsocket_simple_int_recv(req, perrno);
     615    12437388 :         if (ret == 0) {
     616    12317787 :                 ret = state->ret;
     617             :         }
     618             : 
     619    12437388 :         tevent_req_received(req);
     620    12437388 :         return ret;
     621             : }
     622             : 
     623             : struct tstream_writev_state {
     624             :         const struct tstream_context_ops *ops;
     625             :         struct tstream_context *stream;
     626             :         int ret;
     627             : };
     628             : 
     629     3980017 : static int tstream_writev_destructor(struct tstream_writev_state *state)
     630             : {
     631     3980017 :         if (state->stream) {
     632     3980017 :                 state->stream->writev_req = NULL;
     633             :         }
     634             : 
     635     3980017 :         return 0;
     636             : }
     637             : 
     638             : static void tstream_writev_done(struct tevent_req *subreq);
     639             : 
     640     3980017 : 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,
     644             :                                        size_t count)
     645             : {
     646             :         struct tevent_req *req;
     647             :         struct tstream_writev_state *state;
     648             :         struct tevent_req *subreq;
     649     3980017 :         int to_write = 0;
     650             :         size_t i;
     651             : 
     652     3980017 :         req = tevent_req_create(mem_ctx, &state,
     653             :                                 struct tstream_writev_state);
     654     3980017 :         if (req == NULL) {
     655           0 :                 return NULL;
     656             :         }
     657             : 
     658     3980017 :         state->ops = stream->ops;
     659     3980017 :         state->stream = stream;
     660     3980017 :         state->ret = -1;
     661             : 
     662             :         /* first check if the input is ok */
     663             : #ifdef IOV_MAX
     664     3980017 :         if (count > IOV_MAX) {
     665           0 :                 tevent_req_error(req, EMSGSIZE);
     666           0 :                 goto post;
     667             :         }
     668             : #endif
     669             : 
     670    10134846 :         for (i=0; i < count; i++) {
     671     6195007 :                 int tmp = to_write;
     672     6195007 :                 tmp += vector[i].iov_len;
     673             : 
     674     6195007 :                 if (tmp < to_write) {
     675           0 :                         tevent_req_error(req, EMSGSIZE);
     676           0 :                         goto post;
     677             :                 }
     678             : 
     679     6195007 :                 to_write = tmp;
     680             :         }
     681             : 
     682     3980017 :         if (to_write == 0) {
     683           0 :                 tevent_req_error(req, EINVAL);
     684           0 :                 goto post;
     685             :         }
     686             : 
     687     3980017 :         if (stream->writev_req) {
     688           0 :                 tevent_req_error(req, EBUSY);
     689           0 :                 goto post;
     690             :         }
     691     3980017 :         stream->writev_req = req;
     692             : 
     693     3980017 :         talloc_set_destructor(state, tstream_writev_destructor);
     694             : 
     695     3980017 :         subreq = state->ops->writev_send(state, ev, stream, vector, count);
     696     3980017 :         if (tevent_req_nomem(subreq, req)) {
     697           0 :                 goto post;
     698             :         }
     699     3980017 :         tevent_req_set_callback(subreq, tstream_writev_done, req);
     700             : 
     701     3980017 :         return req;
     702             : 
     703           0 :  post:
     704           0 :         tevent_req_post(req, ev);
     705           0 :         return req;
     706             : }
     707             : 
     708     3979948 : static void tstream_writev_done(struct tevent_req *subreq)
     709             : {
     710     3979948 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     711             :                                  struct tevent_req);
     712     3979948 :         struct tstream_writev_state *state = tevent_req_data(req,
     713             :                                              struct tstream_writev_state);
     714             :         ssize_t ret;
     715             :         int sys_errno;
     716             : 
     717     3979948 :         ret = state->ops->writev_recv(subreq, &sys_errno);
     718     3979948 :         if (ret == -1) {
     719          34 :                 tevent_req_error(req, sys_errno);
     720          34 :                 return;
     721             :         }
     722             : 
     723     3979914 :         state->ret = ret;
     724             : 
     725     3979914 :         tevent_req_done(req);
     726             : }
     727             : 
     728     3979948 : int tstream_writev_recv(struct tevent_req *req,
     729             :                        int *perrno)
     730             : {
     731     3979948 :         struct tstream_writev_state *state = tevent_req_data(req,
     732             :                                              struct tstream_writev_state);
     733             :         int ret;
     734             : 
     735     3979948 :         ret = tsocket_simple_int_recv(req, perrno);
     736     3979948 :         if (ret == 0) {
     737     3979914 :                 ret = state->ret;
     738             :         }
     739             : 
     740     3979948 :         tevent_req_received(req);
     741     3979948 :         return ret;
     742             : }
     743             : 
     744             : struct tstream_disconnect_state {
     745             :         const struct tstream_context_ops *ops;
     746             : };
     747             : 
     748             : static void tstream_disconnect_done(struct tevent_req *subreq);
     749             : 
     750       54964 : struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
     751             :                                            struct tevent_context *ev,
     752             :                                            struct tstream_context *stream)
     753             : {
     754             :         struct tevent_req *req;
     755             :         struct tstream_disconnect_state *state;
     756             :         struct tevent_req *subreq;
     757             : 
     758       54964 :         req = tevent_req_create(mem_ctx, &state,
     759             :                                 struct tstream_disconnect_state);
     760       54964 :         if (req == NULL) {
     761           0 :                 return NULL;
     762             :         }
     763             : 
     764       54964 :         state->ops = stream->ops;
     765             : 
     766       54964 :         if (stream->readv_req || stream->writev_req) {
     767          20 :                 tevent_req_error(req, EBUSY);
     768          20 :                 goto post;
     769             :         }
     770             : 
     771       54944 :         subreq = state->ops->disconnect_send(state, ev, stream);
     772       54944 :         if (tevent_req_nomem(subreq, req)) {
     773           0 :                 goto post;
     774             :         }
     775       54944 :         tevent_req_set_callback(subreq, tstream_disconnect_done, req);
     776             : 
     777       54944 :         return req;
     778             : 
     779          20 :  post:
     780          20 :         tevent_req_post(req, ev);
     781          20 :         return req;
     782             : }
     783             : 
     784       36792 : static void tstream_disconnect_done(struct tevent_req *subreq)
     785             : {
     786       36792 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     787             :                                  struct tevent_req);
     788       36792 :         struct tstream_disconnect_state *state = tevent_req_data(req,
     789             :                                                  struct tstream_disconnect_state);
     790             :         int ret;
     791             :         int sys_errno;
     792             : 
     793       36792 :         ret = state->ops->disconnect_recv(subreq, &sys_errno);
     794       36792 :         if (ret == -1) {
     795       17537 :                 tevent_req_error(req, sys_errno);
     796       17537 :                 return;
     797             :         }
     798             : 
     799       19255 :         tevent_req_done(req);
     800             : }
     801             : 
     802       36792 : int tstream_disconnect_recv(struct tevent_req *req,
     803             :                            int *perrno)
     804             : {
     805             :         int ret;
     806             : 
     807       36792 :         ret = tsocket_simple_int_recv(req, perrno);
     808             : 
     809       36792 :         tevent_req_received(req);
     810       36792 :         return ret;
     811             : }
     812             : 

Generated by: LCOV version 1.13