LCOV - code coverage report
Current view: top level - source3/lib - util_tsock.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 48 65 73.8 %
Date: 2024-04-13 12:30:31 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Utilities around tsocket
       4             :    Copyright (C) Volker Lendecke 2009
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "replace.h"
      21             : #include "system/network.h"
      22             : #include <tevent.h>
      23             : #include "lib/util_tsock.h"
      24             : #include "../lib/tsocket/tsocket.h"
      25             : #include "../lib/util/tevent_unix.h"
      26             : 
      27             : struct tstream_read_packet_state {
      28             :         struct tevent_context *ev;
      29             :         struct tstream_context *stream;
      30             :         ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data);
      31             :         void *private_data;
      32             :         uint8_t *buf;
      33             :         struct iovec iov;
      34             : };
      35             : 
      36             : static void tstream_read_packet_done(struct tevent_req *subreq);
      37             : 
      38        2430 : struct tevent_req *tstream_read_packet_send(TALLOC_CTX *mem_ctx,
      39             :                                             struct tevent_context *ev,
      40             :                                             struct tstream_context *stream,
      41             :                                             size_t initial,
      42             :                                             ssize_t (*more)(uint8_t *buf,
      43             :                                                             size_t buflen,
      44             :                                                             void *private_data),
      45             :                                             void *private_data)
      46             : {
      47           0 :         struct tevent_req *req, *subreq;
      48           0 :         struct tstream_read_packet_state *state;
      49             : 
      50        2430 :         req = tevent_req_create(mem_ctx, &state,
      51             :                                 struct tstream_read_packet_state);
      52        2430 :         if (req == NULL) {
      53           0 :                 return NULL;
      54             :         }
      55        2430 :         state->buf = talloc_array(state, uint8_t, initial);
      56        2430 :         if (tevent_req_nomem(state->buf, req)) {
      57           0 :                 return tevent_req_post(req, ev);
      58             :         }
      59        2430 :         state->iov.iov_base = (void *)state->buf;
      60        2430 :         state->iov.iov_len = initial;
      61             : 
      62        2430 :         state->ev = ev;
      63        2430 :         state->stream = stream;
      64        2430 :         state->more = more;
      65        2430 :         state->private_data = private_data;
      66             : 
      67        2430 :         subreq = tstream_readv_send(state, ev, stream, &state->iov, 1);
      68        2430 :         if (tevent_req_nomem(subreq, req)) {
      69           0 :                 return tevent_req_post(req, ev);
      70             :         }
      71        2430 :         tevent_req_set_callback(subreq, tstream_read_packet_done, req);
      72             : 
      73        2430 :         return req;
      74             : }
      75             : 
      76        3233 : static void tstream_read_packet_done(struct tevent_req *subreq)
      77             : {
      78        3233 :         struct tevent_req *req = tevent_req_callback_data(
      79             :                 subreq, struct tevent_req);
      80        3233 :         struct tstream_read_packet_state *state = tevent_req_data(
      81             :                 req, struct tstream_read_packet_state);
      82           0 :         int ret, err;
      83           0 :         size_t total;
      84           0 :         ssize_t more;
      85           0 :         uint8_t *tmp;
      86             : 
      87        3233 :         ret = tstream_readv_recv(subreq, &err);
      88        3233 :         TALLOC_FREE(subreq);
      89        3233 :         if (ret == 0) {
      90           0 :                 err = EPIPE;
      91             :         }
      92        3233 :         if (ret <= 0) {
      93         615 :                 tevent_req_error(req, err);
      94        2134 :                 return;
      95             :         }
      96             : 
      97        2618 :         if (state->more == NULL) {
      98             :                 /* Nobody to ask, this is a async read_data */
      99         301 :                 tevent_req_done(req);
     100         301 :                 return;
     101             :         }
     102        2317 :         total = talloc_array_length(state->buf);
     103             : 
     104        2317 :         more = state->more(state->buf, total, state->private_data);
     105        2317 :         if (more == -1) {
     106             :                 /* We got an invalid packet, tell the caller */
     107           0 :                 tevent_req_error(req, EIO);
     108           0 :                 return;
     109             :         }
     110        2317 :         if (more == 0) {
     111             :                 /* We're done, full packet received */
     112        1218 :                 tevent_req_done(req);
     113        1218 :                 return;
     114             :         }
     115             : 
     116        1099 :         if (total + more < total) {
     117           0 :                 tevent_req_error(req, EMSGSIZE);
     118           0 :                 return;
     119             :         }
     120             : 
     121        1099 :         tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
     122        1099 :         if (tevent_req_nomem(tmp, req)) {
     123           0 :                 return;
     124             :         }
     125        1099 :         state->buf = tmp;
     126             : 
     127        1099 :         state->iov.iov_base = (void *)(state->buf + total);
     128        1099 :         state->iov.iov_len = more;
     129             : 
     130        1099 :         subreq = tstream_readv_send(state, state->ev, state->stream,
     131             :                                     &state->iov, 1);
     132        1099 :         if (tevent_req_nomem(subreq, req)) {
     133           0 :                 return;
     134             :         }
     135        1099 :         tevent_req_set_callback(subreq, tstream_read_packet_done, req);
     136             : }
     137             : 
     138        2134 : ssize_t tstream_read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     139             :                                  uint8_t **pbuf, int *perrno)
     140             : {
     141           0 :         struct tstream_read_packet_state *state =
     142        2134 :                 tevent_req_data(req, struct tstream_read_packet_state);
     143             : 
     144        2134 :         if (tevent_req_is_unix_error(req, perrno)) {
     145         615 :                 return -1;
     146             :         }
     147        1519 :         *pbuf = talloc_move(mem_ctx, &state->buf);
     148        1519 :         return talloc_array_length(*pbuf);
     149             : }

Generated by: LCOV version 1.14