root/opal/mca/event/libevent2022/libevent/test/regress_zlib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zlib_deflate_free
  2. zlib_inflate_free
  3. getstate
  4. zlib_input_filter
  5. zlib_output_filter
  6. readcb
  7. writecb
  8. errorcb
  9. test_bufferevent_zlib

   1 /*
   2  * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  * 3. The name of the author may not be used to endorse or promote products
  13  *    derived from this software without specific prior written permission.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  */
  26 
  27 /* The old tests here need assertions to work. */
  28 #undef NDEBUG
  29 
  30 #ifdef WIN32
  31 #include <winsock2.h>
  32 #include <windows.h>
  33 #endif
  34 
  35 #include "event2/event-config.h"
  36 
  37 #include <sys/types.h>
  38 #ifndef WIN32
  39 #include <sys/socket.h>
  40 #include <sys/wait.h>
  41 #include <unistd.h>
  42 #include <netdb.h>
  43 #endif
  44 #include <signal.h>
  45 #include <stdio.h>
  46 #include <stdlib.h>
  47 #include <string.h>
  48 
  49 #include <assert.h>
  50 #include <errno.h>
  51 
  52 #include "event2/util.h"
  53 #include "event2/event.h"
  54 #include "event2/event_compat.h"
  55 #include "event2/buffer.h"
  56 #include "event2/bufferevent.h"
  57 
  58 #include "regress.h"
  59 
  60 /* zlib 1.2.4 and 1.2.5 do some "clever" things with macros.  Instead of
  61    saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory
  62    that nobody will care if the compile outputs a no-such-identifier warning.
  63 
  64    Sorry, but we like -Werror over here, so I guess we need to define these.
  65    I hope that zlib 1.2.6 doesn't break these too.
  66 */
  67 #ifndef _LARGEFILE64_SOURCE
  68 #define _LARGEFILE64_SOURCE 0
  69 #endif
  70 #ifndef _LFS64_LARGEFILE
  71 #define _LFS64_LARGEFILE 0
  72 #endif
  73 #ifndef _FILE_OFFSET_BITS
  74 #define _FILE_OFFSET_BITS 0
  75 #endif
  76 #ifndef off64_t
  77 #define off64_t ev_int64_t
  78 #endif
  79 
  80 #include <zlib.h>
  81 
  82 static int infilter_calls;
  83 static int outfilter_calls;
  84 static int readcb_finished;
  85 static int writecb_finished;
  86 static int errorcb_invoked;
  87 
  88 /*
  89  * Zlib filters
  90  */
  91 
  92 static void
  93 zlib_deflate_free(void *ctx)
  94 {
  95         z_streamp p = ctx;
  96 
  97         assert(deflateEnd(p) == Z_OK);
  98 }
  99 
 100 static void
 101 zlib_inflate_free(void *ctx)
 102 {
 103         z_streamp p = ctx;
 104 
 105         assert(inflateEnd(p) == Z_OK);
 106 }
 107 
 108 static int
 109 getstate(enum bufferevent_flush_mode state)
 110 {
 111         switch (state) {
 112         case BEV_FINISHED:
 113                 return Z_FINISH;
 114         case BEV_FLUSH:
 115                 return Z_SYNC_FLUSH;
 116         case BEV_NORMAL:
 117         default:
 118                 return Z_NO_FLUSH;
 119         }
 120 }
 121 
 122 /*
 123  * The input filter is triggered only on new input read from the network.
 124  * That means all input data needs to be consumed or the filter needs to
 125  * initiate its own triggering via a timeout.
 126  */
 127 static enum bufferevent_filter_result
 128 zlib_input_filter(struct evbuffer *src, struct evbuffer *dst,
 129     ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx)
 130 {
 131         struct evbuffer_iovec v_in[1];
 132         struct evbuffer_iovec v_out[1];
 133         int nread, nwrite;
 134         int res, n;
 135 
 136         z_streamp p = ctx;
 137 
 138         do {
 139                 /* let's do some decompression */
 140                 n = evbuffer_peek(src, -1, NULL, v_in, 1);
 141                 if (n) {
 142                         p->avail_in = v_in[0].iov_len;
 143                         p->next_in = v_in[0].iov_base;
 144                 } else {
 145                         p->avail_in = 0;
 146                         p->next_in = 0;
 147                 }
 148 
 149                 evbuffer_reserve_space(dst, 4096, v_out, 1);
 150                 p->next_out = v_out[0].iov_base;
 151                 p->avail_out = v_out[0].iov_len;
 152 
 153                 /* we need to flush zlib if we got a flush */
 154                 res = inflate(p, getstate(state));
 155 
 156                 /* let's figure out how much was compressed */
 157                 nread = v_in[0].iov_len - p->avail_in;
 158                 nwrite = v_out[0].iov_len - p->avail_out;
 159 
 160                 evbuffer_drain(src, nread);
 161                 v_out[0].iov_len = nwrite;
 162                 evbuffer_commit_space(dst, v_out, 1);
 163 
 164                 if (res==Z_BUF_ERROR) {
 165                         /* We're out of space, or out of decodeable input.
 166                            Only if nwrite == 0 assume the latter.
 167                          */
 168                         if (nwrite == 0)
 169                                 return BEV_NEED_MORE;
 170                 } else {
 171                         assert(res == Z_OK || res == Z_STREAM_END);
 172                 }
 173 
 174         } while (evbuffer_get_length(src) > 0);
 175 
 176         ++infilter_calls;
 177 
 178         return (BEV_OK);
 179 }
 180 
 181 static enum bufferevent_filter_result
 182 zlib_output_filter(struct evbuffer *src, struct evbuffer *dst,
 183     ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx)
 184 {
 185         struct evbuffer_iovec v_in[1];
 186         struct evbuffer_iovec v_out[1];
 187         int nread, nwrite;
 188         int res, n;
 189 
 190         z_streamp p = ctx;
 191 
 192         do {
 193                 /* let's do some compression */
 194                 n = evbuffer_peek(src, -1, NULL, v_in, 1);
 195                 if (n) {
 196                         p->avail_in = v_in[0].iov_len;
 197                         p->next_in = v_in[0].iov_base;
 198                 } else {
 199                         p->avail_in = 0;
 200                         p->next_in = 0;
 201                 }
 202 
 203                 evbuffer_reserve_space(dst, 4096, v_out, 1);
 204                 p->next_out = v_out[0].iov_base;
 205                 p->avail_out = v_out[0].iov_len;
 206 
 207                 /* we need to flush zlib if we got a flush */
 208                 res = deflate(p, getstate(state));
 209 
 210                 /* let's figure out how much was decompressed */
 211                 nread = v_in[0].iov_len - p->avail_in;
 212                 nwrite = v_out[0].iov_len - p->avail_out;
 213 
 214                 evbuffer_drain(src, nread);
 215                 v_out[0].iov_len = nwrite;
 216                 evbuffer_commit_space(dst, v_out, 1);
 217 
 218                 if (res==Z_BUF_ERROR) {
 219                         /* We're out of space, or out of decodeable input.
 220                            Only if nwrite == 0 assume the latter.
 221                          */
 222                         if (nwrite == 0)
 223                                 return BEV_NEED_MORE;
 224                 } else {
 225                         assert(res == Z_OK || res == Z_STREAM_END);
 226                 }
 227 
 228         } while (evbuffer_get_length(src) > 0);
 229 
 230         ++outfilter_calls;
 231 
 232         return (BEV_OK);
 233 }
 234 
 235 /*
 236  * simple bufferevent test (over transparent zlib treatment)
 237  */
 238 
 239 static void
 240 readcb(struct bufferevent *bev, void *arg)
 241 {
 242         if (evbuffer_get_length(bufferevent_get_input(bev)) == 8333) {
 243                 struct evbuffer *evbuf = evbuffer_new();
 244                 assert(evbuf != NULL);
 245 
 246                 /* gratuitous test of bufferevent_read_buffer */
 247                 bufferevent_read_buffer(bev, evbuf);
 248 
 249                 bufferevent_disable(bev, EV_READ);
 250 
 251                 if (evbuffer_get_length(evbuf) == 8333) {
 252                         ++readcb_finished;
 253                 }
 254 
 255                 evbuffer_free(evbuf);
 256         }
 257 }
 258 
 259 static void
 260 writecb(struct bufferevent *bev, void *arg)
 261 {
 262         if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
 263                 ++writecb_finished;
 264         }
 265 }
 266 
 267 static void
 268 errorcb(struct bufferevent *bev, short what, void *arg)
 269 {
 270         errorcb_invoked = 1;
 271 }
 272 
 273 void
 274 test_bufferevent_zlib(void *arg)
 275 {
 276         struct bufferevent *bev1=NULL, *bev2=NULL;
 277         char buffer[8333];
 278         z_stream z_input, z_output;
 279         int i, r;
 280         evutil_socket_t pair[2] = {-1, -1};
 281         (void)arg;
 282 
 283         infilter_calls = outfilter_calls = readcb_finished = writecb_finished
 284             = errorcb_invoked = 0;
 285 
 286         if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
 287                 tt_abort_perror("socketpair");
 288         }
 289 
 290         evutil_make_socket_nonblocking(pair[0]);
 291         evutil_make_socket_nonblocking(pair[1]);
 292 
 293         bev1 = bufferevent_socket_new(NULL, pair[0], 0);
 294         bev2 = bufferevent_socket_new(NULL, pair[1], 0);
 295 
 296         memset(&z_output, 0, sizeof(z_output));
 297         r = deflateInit(&z_output, Z_DEFAULT_COMPRESSION);
 298         tt_int_op(r, ==, Z_OK);
 299         memset(&z_input, 0, sizeof(z_input));
 300         r = inflateInit(&z_input);
 301         tt_int_op(r, ==, Z_OK);
 302 
 303         /* initialize filters */
 304         bev1 = bufferevent_filter_new(bev1, NULL, zlib_output_filter,
 305             BEV_OPT_CLOSE_ON_FREE, zlib_deflate_free, &z_output);
 306         bev2 = bufferevent_filter_new(bev2, zlib_input_filter,
 307             NULL, BEV_OPT_CLOSE_ON_FREE, zlib_inflate_free, &z_input);
 308         bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL);
 309         bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL);
 310 
 311         bufferevent_disable(bev1, EV_READ);
 312         bufferevent_enable(bev1, EV_WRITE);
 313 
 314         bufferevent_enable(bev2, EV_READ);
 315 
 316         for (i = 0; i < (int)sizeof(buffer); i++)
 317                 buffer[i] = i;
 318 
 319         /* break it up into multiple buffer chains */
 320         bufferevent_write(bev1, buffer, 1800);
 321         bufferevent_write(bev1, buffer + 1800, sizeof(buffer) - 1800);
 322 
 323         /* we are done writing - we need to flush everything */
 324         bufferevent_flush(bev1, EV_WRITE, BEV_FINISHED);
 325 
 326         event_dispatch();
 327 
 328         tt_want(infilter_calls);
 329         tt_want(outfilter_calls);
 330         tt_want(readcb_finished);
 331         tt_want(writecb_finished);
 332         tt_want(!errorcb_invoked);
 333 
 334         test_ok = 1;
 335 end:
 336         if (bev1)
 337                 bufferevent_free(bev1);
 338         if (bev2)
 339                 bufferevent_free(bev2);
 340 
 341         if (pair[0] >= 0)
 342                 evutil_closesocket(pair[0]);
 343         if (pair[1] >= 0)
 344                 evutil_closesocket(pair[1]);
 345 }

/* [<][>][^][v][top][bottom][index][help] */