LCOV - code coverage report
Current view: top level - lib/tsocket - tsocket.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 294 389 75.6 %
Date: 2024-05-31 13:13:24 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    62349576 : int tsocket_simple_int_recv(struct tevent_req *req, int *perrno)
      30             : {
      31      352612 :         enum tevent_req_state state;
      32      352612 :         uint64_t error;
      33             : 
      34    62349576 :         if (!tevent_req_is_error(req, &state, &error)) {
      35    61369204 :                 return 0;
      36             :         }
      37             : 
      38      637672 :         switch (state) {
      39           6 :         case TEVENT_REQ_NO_MEMORY:
      40           6 :                 *perrno = ENOMEM;
      41           6 :                 return -1;
      42           2 :         case TEVENT_REQ_TIMED_OUT:
      43           2 :                 *perrno = ETIMEDOUT;
      44           2 :                 return -1;
      45      637664 :         case TEVENT_REQ_USER_ERROR:
      46      637664 :                 *perrno = (int)error;
      47      637664 :                 return -1;
      48           0 :         default:
      49           0 :                 break;
      50             :         }
      51             : 
      52           0 :         *perrno = EIO;
      53           0 :         return -1;
      54             : }
      55             : 
      56     1121139 : 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     1121139 :         void **ppstate = (void **)pstate;
      64       23413 :         struct tsocket_address *addr;
      65             : 
      66     1121139 :         addr = talloc_zero(mem_ctx, struct tsocket_address);
      67     1121139 :         if (!addr) {
      68           0 :                 return NULL;
      69             :         }
      70     1121139 :         addr->ops = ops;
      71     1121139 :         addr->location = location;
      72     1121139 :         addr->private_data = talloc_size(addr, psize);
      73     1121139 :         if (!addr->private_data) {
      74           0 :                 talloc_free(addr);
      75           0 :                 return NULL;
      76             :         }
      77     1121139 :         talloc_set_name_const(addr->private_data, type);
      78             : 
      79     1121139 :         *ppstate = addr->private_data;
      80     1121139 :         return addr;
      81             : }
      82             : 
      83      908474 : char *tsocket_address_string(const struct tsocket_address *addr,
      84             :                              TALLOC_CTX *mem_ctx)
      85             : {
      86      908474 :         if (!addr) {
      87           0 :                 return talloc_strdup(mem_ctx, "NULL");
      88             :         }
      89      908474 :         return addr->ops->string(addr, mem_ctx);
      90             : }
      91             : 
      92      393933 : struct tsocket_address *_tsocket_address_copy(const struct tsocket_address *addr,
      93             :                                               TALLOC_CTX *mem_ctx,
      94             :                                               const char *location)
      95             : {
      96      393933 :         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        7024 : static int tdgram_context_destructor(struct tdgram_context *dgram)
     109             : {
     110        7024 :         if (dgram->recvfrom_req) {
     111           0 :                 tevent_req_received(dgram->recvfrom_req);
     112             :         }
     113             : 
     114        7024 :         if (dgram->sendto_req) {
     115           0 :                 tevent_req_received(dgram->sendto_req);
     116             :         }
     117             : 
     118        7024 :         return 0;
     119             : }
     120             : 
     121        6485 : 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          68 :         struct tdgram_context *dgram;
     129        6485 :         void **ppstate = (void **)pstate;
     130          68 :         void *state;
     131             : 
     132        6485 :         dgram = talloc(mem_ctx, struct tdgram_context);
     133        6485 :         if (dgram == NULL) {
     134           0 :                 return NULL;
     135             :         }
     136        6485 :         dgram->location              = location;
     137        6485 :         dgram->ops           = ops;
     138        6485 :         dgram->recvfrom_req  = NULL;
     139        6485 :         dgram->sendto_req    = NULL;
     140             : 
     141        6485 :         state = talloc_size(dgram, psize);
     142        6485 :         if (state == NULL) {
     143           0 :                 talloc_free(dgram);
     144           0 :                 return NULL;
     145             :         }
     146        6485 :         talloc_set_name_const(state, type);
     147             : 
     148        6485 :         dgram->private_data = state;
     149             : 
     150        6485 :         talloc_set_destructor(dgram, tdgram_context_destructor);
     151             : 
     152        6485 :         *ppstate = state;
     153        6485 :         return dgram;
     154             : }
     155             : 
     156      238761 : void *_tdgram_context_data(struct tdgram_context *dgram)
     157             : {
     158      238761 :         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       39739 : static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state *state)
     170             : {
     171       39739 :         if (state->dgram) {
     172       39739 :                 state->dgram->recvfrom_req = NULL;
     173             :         }
     174             : 
     175       39739 :         return 0;
     176             : }
     177             : 
     178             : static void tdgram_recvfrom_done(struct tevent_req *subreq);
     179             : 
     180       39200 : struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
     181             :                                         struct tevent_context *ev,
     182             :                                         struct tdgram_context *dgram)
     183             : {
     184        1288 :         struct tevent_req *req;
     185        1288 :         struct tdgram_recvfrom_state *state;
     186        1288 :         struct tevent_req *subreq;
     187             : 
     188       39200 :         req = tevent_req_create(mem_ctx, &state,
     189             :                                 struct tdgram_recvfrom_state);
     190       39200 :         if (req == NULL) {
     191           0 :                 return NULL;
     192             :         }
     193             : 
     194       39200 :         state->ops = dgram->ops;
     195       39200 :         state->dgram = dgram;
     196       39200 :         state->buf = NULL;
     197       39200 :         state->len = 0;
     198       39200 :         state->src = NULL;
     199             : 
     200       39200 :         if (dgram->recvfrom_req) {
     201           0 :                 tevent_req_error(req, EBUSY);
     202           0 :                 goto post;
     203             :         }
     204       39200 :         dgram->recvfrom_req = req;
     205             : 
     206       39200 :         talloc_set_destructor(state, tdgram_recvfrom_destructor);
     207             : 
     208       39200 :         subreq = state->ops->recvfrom_send(state, ev, dgram);
     209       39200 :         if (tevent_req_nomem(subreq, req)) {
     210           0 :                 goto post;
     211             :         }
     212       39200 :         tevent_req_set_callback(subreq, tdgram_recvfrom_done, req);
     213             : 
     214       39200 :         return req;
     215             : 
     216           0 :  post:
     217           0 :         tevent_req_post(req, ev);
     218           0 :         return req;
     219             : }
     220             : 
     221       37756 : static void tdgram_recvfrom_done(struct tevent_req *subreq)
     222             : {
     223       37756 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     224             :                                  struct tevent_req);
     225       37756 :         struct tdgram_recvfrom_state *state = tevent_req_data(req,
     226             :                                               struct tdgram_recvfrom_state);
     227        1256 :         ssize_t ret;
     228        1256 :         int sys_errno;
     229             : 
     230       37756 :         ret = state->ops->recvfrom_recv(subreq, &sys_errno, state,
     231             :                                         &state->buf, &state->src);
     232       37756 :         if (ret == -1) {
     233           6 :                 tevent_req_error(req, sys_errno);
     234           6 :                 return;
     235             :         }
     236             : 
     237       37750 :         state->len = ret;
     238             : 
     239       37750 :         tevent_req_done(req);
     240             : }
     241             : 
     242       37756 : 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       37756 :         struct tdgram_recvfrom_state *state = tevent_req_data(req,
     249             :                                               struct tdgram_recvfrom_state);
     250        1256 :         ssize_t ret;
     251             : 
     252       37756 :         ret = tsocket_simple_int_recv(req, perrno);
     253       37756 :         if (ret == 0) {
     254       37750 :                 *buf = talloc_move(mem_ctx, &state->buf);
     255       37750 :                 ret = state->len;
     256       37750 :                 if (src) {
     257       35243 :                         *src = talloc_move(mem_ctx, &state->src);
     258             :                 }
     259             :         }
     260             : 
     261       37756 :         tevent_req_received(req);
     262       37756 :         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       38192 : static int tdgram_sendto_destructor(struct tdgram_sendto_state *state)
     272             : {
     273       38192 :         if (state->dgram) {
     274       38192 :                 state->dgram->sendto_req = NULL;
     275             :         }
     276             : 
     277       38192 :         return 0;
     278             : }
     279             : 
     280             : static void tdgram_sendto_done(struct tevent_req *subreq);
     281             : 
     282       38192 : 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        1256 :         struct tevent_req *req;
     289        1256 :         struct tdgram_sendto_state *state;
     290        1256 :         struct tevent_req *subreq;
     291             : 
     292       38192 :         req = tevent_req_create(mem_ctx, &state,
     293             :                                 struct tdgram_sendto_state);
     294       38192 :         if (req == NULL) {
     295           0 :                 return NULL;
     296             :         }
     297             : 
     298       38192 :         state->ops = dgram->ops;
     299       38192 :         state->dgram = dgram;
     300       38192 :         state->ret = -1;
     301             : 
     302       38192 :         if (len == 0) {
     303           0 :                 tevent_req_error(req, EINVAL);
     304           0 :                 goto post;
     305             :         }
     306             : 
     307       38192 :         if (dgram->sendto_req) {
     308           0 :                 tevent_req_error(req, EBUSY);
     309           0 :                 goto post;
     310             :         }
     311       38192 :         dgram->sendto_req = req;
     312             : 
     313       38192 :         talloc_set_destructor(state, tdgram_sendto_destructor);
     314             : 
     315       38192 :         subreq = state->ops->sendto_send(state, ev, dgram,
     316             :                                          buf, len, dst);
     317       38192 :         if (tevent_req_nomem(subreq, req)) {
     318           0 :                 goto post;
     319             :         }
     320       38192 :         tevent_req_set_callback(subreq, tdgram_sendto_done, req);
     321             : 
     322       38192 :         return req;
     323             : 
     324           0 :  post:
     325           0 :         tevent_req_post(req, ev);
     326           0 :         return req;
     327             : }
     328             : 
     329       38192 : static void tdgram_sendto_done(struct tevent_req *subreq)
     330             : {
     331       38192 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     332             :                                  struct tevent_req);
     333       38192 :         struct tdgram_sendto_state *state = tevent_req_data(req,
     334             :                                             struct tdgram_sendto_state);
     335        1256 :         ssize_t ret;
     336        1256 :         int sys_errno;
     337             : 
     338       38192 :         ret = state->ops->sendto_recv(subreq, &sys_errno);
     339       38192 :         if (ret == -1) {
     340          57 :                 tevent_req_error(req, sys_errno);
     341          57 :                 return;
     342             :         }
     343             : 
     344       38135 :         state->ret = ret;
     345             : 
     346       38135 :         tevent_req_done(req);
     347             : }
     348             : 
     349       38192 : ssize_t tdgram_sendto_recv(struct tevent_req *req,
     350             :                            int *perrno)
     351             : {
     352       38192 :         struct tdgram_sendto_state *state = tevent_req_data(req,
     353             :                                             struct tdgram_sendto_state);
     354        1256 :         ssize_t ret;
     355             : 
     356       38192 :         ret = tsocket_simple_int_recv(req, perrno);
     357       38192 :         if (ret == 0) {
     358       38135 :                 ret = state->ret;
     359             :         }
     360             : 
     361       38192 :         tevent_req_received(req);
     362       38192 :         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           0 :         struct tevent_req *req;
     376           0 :         struct tdgram_disconnect_state *state;
     377           0 :         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           0 :         int ret;
     412           0 :         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           0 :         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      491223 : static int tstream_context_destructor(struct tstream_context *stream)
     444             : {
     445      491223 :         if (stream->readv_req) {
     446           0 :                 tevent_req_received(stream->readv_req);
     447             :         }
     448             : 
     449      491223 :         if (stream->writev_req) {
     450          66 :                 tevent_req_received(stream->writev_req);
     451             :         }
     452             : 
     453      491223 :         return 0;
     454             : }
     455             : 
     456      488832 : 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        6375 :         struct tstream_context *stream;
     464      488832 :         void **ppstate = (void **)pstate;
     465        6375 :         void *state;
     466             : 
     467      488832 :         stream = talloc(mem_ctx, struct tstream_context);
     468      488832 :         if (stream == NULL) {
     469           0 :                 return NULL;
     470             :         }
     471      488832 :         stream->location     = location;
     472      488832 :         stream->ops          = ops;
     473      488832 :         stream->readv_req    = NULL;
     474      488832 :         stream->writev_req   = NULL;
     475             : 
     476      488832 :         state = talloc_size(stream, psize);
     477      488832 :         if (state == NULL) {
     478           0 :                 talloc_free(stream);
     479           0 :                 return NULL;
     480             :         }
     481      488832 :         talloc_set_name_const(state, type);
     482             : 
     483      488832 :         stream->private_data = state;
     484             : 
     485      488832 :         talloc_set_destructor(stream, tstream_context_destructor);
     486             : 
     487      488832 :         *ppstate = state;
     488      488832 :         return stream;
     489             : }
     490             : 
     491   116596914 : void *_tstream_context_data(struct tstream_context *stream)
     492             : {
     493   116596914 :         return stream->private_data;
     494             : }
     495             : 
     496     1460245 : ssize_t tstream_pending_bytes(struct tstream_context *stream)
     497             : {
     498     1460245 :         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    17433163 : static int tstream_readv_destructor(struct tstream_readv_state *state)
     508             : {
     509    17433163 :         if (state->stream) {
     510    17433163 :                 state->stream->readv_req = NULL;
     511             :         }
     512             : 
     513    17433163 :         return 0;
     514             : }
     515             : 
     516             : static void tstream_readv_done(struct tevent_req *subreq);
     517             : 
     518    17430516 : 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       91415 :         struct tevent_req *req;
     525       91415 :         struct tstream_readv_state *state;
     526       91415 :         struct tevent_req *subreq;
     527    17430516 :         int to_read = 0;
     528       91415 :         size_t i;
     529             : 
     530    17430516 :         req = tevent_req_create(mem_ctx, &state,
     531             :                                 struct tstream_readv_state);
     532    17430516 :         if (req == NULL) {
     533           0 :                 return NULL;
     534             :         }
     535             : 
     536    17430516 :         state->ops = stream->ops;
     537    17430516 :         state->stream = stream;
     538    17430516 :         state->ret = -1;
     539             : 
     540             :         /* first check if the input is ok */
     541             : #ifdef IOV_MAX
     542    17430516 :         if (count > IOV_MAX) {
     543           0 :                 tevent_req_error(req, EMSGSIZE);
     544           0 :                 goto post;
     545             :         }
     546             : #endif
     547             : 
     548    36533887 :         for (i=0; i < count; i++) {
     549    19103371 :                 int tmp = to_read;
     550    19103371 :                 tmp += vector[i].iov_len;
     551             : 
     552    19103371 :                 if (tmp < to_read) {
     553           0 :                         tevent_req_error(req, EMSGSIZE);
     554           0 :                         goto post;
     555             :                 }
     556             : 
     557    19103371 :                 to_read = tmp;
     558             :         }
     559             : 
     560    17430516 :         if (to_read == 0) {
     561           0 :                 tevent_req_error(req, EINVAL);
     562           0 :                 goto post;
     563             :         }
     564             : 
     565    17430516 :         if (stream->readv_req) {
     566           0 :                 tevent_req_error(req, EBUSY);
     567           0 :                 goto post;
     568             :         }
     569    17430516 :         stream->readv_req = req;
     570             : 
     571    17430516 :         talloc_set_destructor(state, tstream_readv_destructor);
     572             : 
     573    17430516 :         subreq = state->ops->readv_send(state, ev, stream, vector, count);
     574    17430516 :         if (tevent_req_nomem(subreq, req)) {
     575           0 :                 goto post;
     576             :         }
     577    17430516 :         tevent_req_set_callback(subreq, tstream_readv_done, req);
     578             : 
     579    17430516 :         return req;
     580             : 
     581           0 :  post:
     582           0 :         tevent_req_post(req, ev);
     583           0 :         return req;
     584             : }
     585             : 
     586    17429644 : static void tstream_readv_done(struct tevent_req *subreq)
     587             : {
     588    17429644 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     589             :                                  struct tevent_req);
     590    17429644 :         struct tstream_readv_state *state = tevent_req_data(req,
     591             :                                             struct tstream_readv_state);
     592       91402 :         ssize_t ret;
     593       91402 :         int sys_errno;
     594             : 
     595    17429644 :         ret = state->ops->readv_recv(subreq, &sys_errno);
     596    17429644 :         TALLOC_FREE(subreq);
     597    17429644 :         if (ret == -1) {
     598      230567 :                 tevent_req_error(req, sys_errno);
     599      230072 :                 return;
     600             :         }
     601             : 
     602    17199077 :         state->ret = ret;
     603             : 
     604    17199077 :         tevent_req_done(req);
     605             : }
     606             : 
     607    17429644 : int tstream_readv_recv(struct tevent_req *req,
     608             :                        int *perrno)
     609             : {
     610    17429644 :         struct tstream_readv_state *state = tevent_req_data(req,
     611             :                                             struct tstream_readv_state);
     612       91402 :         int ret;
     613             : 
     614    17429644 :         ret = tsocket_simple_int_recv(req, perrno);
     615    17429644 :         if (ret == 0) {
     616    17199077 :                 ret = state->ret;
     617             :         }
     618             : 
     619    17429644 :         tevent_req_received(req);
     620    17429644 :         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     7847277 : static int tstream_writev_destructor(struct tstream_writev_state *state)
     630             : {
     631     7847277 :         if (state->stream) {
     632     7847277 :                 state->stream->writev_req = NULL;
     633             :         }
     634             : 
     635     7847277 :         return 0;
     636             : }
     637             : 
     638             : static void tstream_writev_done(struct tevent_req *subreq);
     639             : 
     640     7847277 : 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       43421 :         struct tevent_req *req;
     647       43421 :         struct tstream_writev_state *state;
     648       43421 :         struct tevent_req *subreq;
     649     7847277 :         int to_write = 0;
     650       43421 :         size_t i;
     651             : 
     652     7847277 :         req = tevent_req_create(mem_ctx, &state,
     653             :                                 struct tstream_writev_state);
     654     7847277 :         if (req == NULL) {
     655           0 :                 return NULL;
     656             :         }
     657             : 
     658     7847277 :         state->ops = stream->ops;
     659     7847277 :         state->stream = stream;
     660     7847277 :         state->ret = -1;
     661             : 
     662             :         /* first check if the input is ok */
     663             : #ifdef IOV_MAX
     664     7847277 :         if (count > IOV_MAX) {
     665           0 :                 tevent_req_error(req, EMSGSIZE);
     666           0 :                 goto post;
     667             :         }
     668             : #endif
     669             : 
     670    19332171 :         for (i=0; i < count; i++) {
     671    11484894 :                 int tmp = to_write;
     672    11484894 :                 tmp += vector[i].iov_len;
     673             : 
     674    11484894 :                 if (tmp < to_write) {
     675           0 :                         tevent_req_error(req, EMSGSIZE);
     676           0 :                         goto post;
     677             :                 }
     678             : 
     679    11484894 :                 to_write = tmp;
     680             :         }
     681             : 
     682     7847277 :         if (to_write == 0) {
     683           0 :                 tevent_req_error(req, EINVAL);
     684           0 :                 goto post;
     685             :         }
     686             : 
     687     7847277 :         if (stream->writev_req) {
     688           0 :                 tevent_req_error(req, EBUSY);
     689           0 :                 goto post;
     690             :         }
     691     7847277 :         stream->writev_req = req;
     692             : 
     693     7847277 :         talloc_set_destructor(state, tstream_writev_destructor);
     694             : 
     695     7847277 :         subreq = state->ops->writev_send(state, ev, stream, vector, count);
     696     7847277 :         if (tevent_req_nomem(subreq, req)) {
     697           0 :                 goto post;
     698             :         }
     699     7847277 :         tevent_req_set_callback(subreq, tstream_writev_done, req);
     700             : 
     701     7847277 :         return req;
     702             : 
     703           0 :  post:
     704           0 :         tevent_req_post(req, ev);
     705           0 :         return req;
     706             : }
     707             : 
     708     7847177 : static void tstream_writev_done(struct tevent_req *subreq)
     709             : {
     710     7847177 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     711             :                                  struct tevent_req);
     712     7847177 :         struct tstream_writev_state *state = tevent_req_data(req,
     713             :                                              struct tstream_writev_state);
     714       43419 :         ssize_t ret;
     715       43419 :         int sys_errno;
     716             : 
     717     7847177 :         ret = state->ops->writev_recv(subreq, &sys_errno);
     718     7847177 :         if (ret == -1) {
     719          38 :                 tevent_req_error(req, sys_errno);
     720          38 :                 return;
     721             :         }
     722             : 
     723     7847139 :         state->ret = ret;
     724             : 
     725     7847139 :         tevent_req_done(req);
     726             : }
     727             : 
     728     7847179 : int tstream_writev_recv(struct tevent_req *req,
     729             :                        int *perrno)
     730             : {
     731     7847179 :         struct tstream_writev_state *state = tevent_req_data(req,
     732             :                                              struct tstream_writev_state);
     733       43421 :         int ret;
     734             : 
     735     7847179 :         ret = tsocket_simple_int_recv(req, perrno);
     736     7847179 :         if (ret == 0) {
     737     7847139 :                 ret = state->ret;
     738             :         }
     739             : 
     740     7847179 :         tevent_req_received(req);
     741     7847179 :         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       74746 : struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
     751             :                                            struct tevent_context *ev,
     752             :                                            struct tstream_context *stream)
     753             : {
     754        1111 :         struct tevent_req *req;
     755        1111 :         struct tstream_disconnect_state *state;
     756        1111 :         struct tevent_req *subreq;
     757             : 
     758       74746 :         req = tevent_req_create(mem_ctx, &state,
     759             :                                 struct tstream_disconnect_state);
     760       74746 :         if (req == NULL) {
     761           0 :                 return NULL;
     762             :         }
     763             : 
     764       74746 :         state->ops = stream->ops;
     765             : 
     766       74746 :         if (stream->readv_req || stream->writev_req) {
     767          20 :                 tevent_req_error(req, EBUSY);
     768          20 :                 goto post;
     769             :         }
     770             : 
     771       74726 :         subreq = state->ops->disconnect_send(state, ev, stream);
     772       74726 :         if (tevent_req_nomem(subreq, req)) {
     773           0 :                 goto post;
     774             :         }
     775       74726 :         tevent_req_set_callback(subreq, tstream_disconnect_done, req);
     776             : 
     777       74726 :         return req;
     778             : 
     779          20 :  post:
     780          20 :         tevent_req_post(req, ev);
     781          20 :         return req;
     782             : }
     783             : 
     784       54803 : static void tstream_disconnect_done(struct tevent_req *subreq)
     785             : {
     786       54803 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     787             :                                  struct tevent_req);
     788       54803 :         struct tstream_disconnect_state *state = tevent_req_data(req,
     789             :                                                  struct tstream_disconnect_state);
     790         244 :         int ret;
     791         244 :         int sys_errno;
     792             : 
     793       54803 :         ret = state->ops->disconnect_recv(subreq, &sys_errno);
     794       54803 :         if (ret == -1) {
     795       26673 :                 tevent_req_error(req, sys_errno);
     796       26673 :                 return;
     797             :         }
     798             : 
     799       28130 :         tevent_req_done(req);
     800             : }
     801             : 
     802       54803 : int tstream_disconnect_recv(struct tevent_req *req,
     803             :                            int *perrno)
     804             : {
     805         244 :         int ret;
     806             : 
     807       54803 :         ret = tsocket_simple_int_recv(req, perrno);
     808             : 
     809       54803 :         tevent_req_received(req);
     810       54803 :         return ret;
     811             : }
     812             : 

Generated by: LCOV version 1.14