LCOV - code coverage report
Current view: top level - source3/lib - util_tsock.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 49 59 83.1 %
Date: 2021-09-23 10:06:22 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        1606 : 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             :         struct tevent_req *req, *subreq;
      48             :         struct tstream_read_packet_state *state;
      49             : 
      50        1606 :         req = tevent_req_create(mem_ctx, &state,
      51             :                                 struct tstream_read_packet_state);
      52        1606 :         if (req == NULL) {
      53           0 :                 return NULL;
      54             :         }
      55        1606 :         state->buf = talloc_array(state, uint8_t, initial);
      56        1606 :         if (tevent_req_nomem(state->buf, req)) {
      57           0 :                 return tevent_req_post(req, ev);
      58             :         }
      59        1606 :         state->iov.iov_base = (void *)state->buf;
      60        1606 :         state->iov.iov_len = initial;
      61             : 
      62        1606 :         state->ev = ev;
      63        1606 :         state->stream = stream;
      64        1606 :         state->more = more;
      65        1606 :         state->private_data = private_data;
      66             : 
      67        1606 :         subreq = tstream_readv_send(state, ev, stream, &state->iov, 1);
      68        1606 :         if (tevent_req_nomem(subreq, req)) {
      69           0 :                 return tevent_req_post(req, ev);
      70             :         }
      71        1606 :         tevent_req_set_callback(subreq, tstream_read_packet_done, req);
      72             : 
      73        1606 :         return req;
      74             : }
      75             : 
      76        2400 : static void tstream_read_packet_done(struct tevent_req *subreq)
      77             : {
      78        2400 :         struct tevent_req *req = tevent_req_callback_data(
      79             :                 subreq, struct tevent_req);
      80        2400 :         struct tstream_read_packet_state *state = tevent_req_data(
      81             :                 req, struct tstream_read_packet_state);
      82             :         int ret, err;
      83             :         size_t total;
      84             :         ssize_t more;
      85             :         uint8_t *tmp;
      86             : 
      87        2400 :         ret = tstream_readv_recv(subreq, &err);
      88        2400 :         TALLOC_FREE(subreq);
      89        2400 :         if (ret == 0) {
      90           0 :                 err = EPIPE;
      91             :         }
      92        2400 :         if (ret <= 0) {
      93         275 :                 tevent_req_error(req, err);
      94         639 :                 return;
      95             :         }
      96             : 
      97        2125 :         if (state->more == NULL) {
      98             :                 /* Nobody to ask, this is a async read_data */
      99         247 :                 tevent_req_done(req);
     100         247 :                 return;
     101             :         }
     102        1878 :         total = talloc_array_length(state->buf);
     103             : 
     104        1878 :         more = state->more(state->buf, total, state->private_data);
     105        1878 :         if (more == -1) {
     106             :                 /* We got an invalid packet, tell the caller */
     107           0 :                 tevent_req_error(req, EIO);
     108           0 :                 return;
     109             :         }
     110        1878 :         if (more == 0) {
     111             :                 /* We're done, full packet received */
     112         842 :                 tevent_req_done(req);
     113         842 :                 return;
     114             :         }
     115             : 
     116        1036 :         if (total + more < total) {
     117           0 :                 tevent_req_error(req, EMSGSIZE);
     118           0 :                 return;
     119             :         }
     120             : 
     121        1036 :         tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
     122        1036 :         if (tevent_req_nomem(tmp, req)) {
     123           0 :                 return;
     124             :         }
     125        1036 :         state->buf = tmp;
     126             : 
     127        1036 :         state->iov.iov_base = (void *)(state->buf + total);
     128        1036 :         state->iov.iov_len = more;
     129             : 
     130        1036 :         subreq = tstream_readv_send(state, state->ev, state->stream,
     131             :                                     &state->iov, 1);
     132        1036 :         if (tevent_req_nomem(subreq, req)) {
     133           0 :                 return;
     134             :         }
     135        1036 :         tevent_req_set_callback(subreq, tstream_read_packet_done, req);
     136             : }
     137             : 
     138        1364 : ssize_t tstream_read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     139             :                                  uint8_t **pbuf, int *perrno)
     140             : {
     141         955 :         struct tstream_read_packet_state *state =
     142        1364 :                 tevent_req_data(req, struct tstream_read_packet_state);
     143             : 
     144        1364 :         if (tevent_req_is_unix_error(req, perrno)) {
     145         275 :                 return -1;
     146             :         }
     147        1089 :         *pbuf = talloc_move(mem_ctx, &state->buf);
     148        1089 :         return talloc_array_length(*pbuf);
     149             : }

Generated by: LCOV version 1.13