1275970Scy/* 2275970Scy * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy 27275970Scy/* The old tests here need assertions to work. */ 28275970Scy#undef NDEBUG 29275970Scy 30275970Scy#ifdef _WIN32 31275970Scy#include <winsock2.h> 32275970Scy#include <windows.h> 33275970Scy#endif 34275970Scy 35275970Scy#include "event2/event-config.h" 36275970Scy 37275970Scy#include <sys/types.h> 38275970Scy#ifndef _WIN32 39275970Scy#include <sys/socket.h> 40275970Scy#include <sys/wait.h> 41275970Scy#include <unistd.h> 42275970Scy#include <netdb.h> 43275970Scy#endif 44275970Scy#include <signal.h> 45275970Scy#include <stdio.h> 46275970Scy#include <stdlib.h> 47275970Scy#include <string.h> 48275970Scy 49275970Scy#include <assert.h> 50275970Scy#include <errno.h> 51275970Scy 52275970Scy#include "event2/util.h" 53275970Scy#include "event2/event.h" 54275970Scy#include "event2/event_compat.h" 55275970Scy#include "event2/buffer.h" 56275970Scy#include "event2/bufferevent.h" 57275970Scy 58275970Scy#include "regress.h" 59282408Scy#include "mm-internal.h" 60275970Scy 61275970Scy/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros. Instead of 62275970Scy saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory 63275970Scy that nobody will care if the compile outputs a no-such-identifier warning. 64275970Scy 65275970Scy Sorry, but we like -Werror over here, so I guess we need to define these. 66275970Scy I hope that zlib 1.2.6 doesn't break these too. 67275970Scy*/ 68275970Scy#ifndef _LARGEFILE64_SOURCE 69275970Scy#define _LARGEFILE64_SOURCE 0 70275970Scy#endif 71275970Scy#ifndef _LFS64_LARGEFILE 72275970Scy#define _LFS64_LARGEFILE 0 73275970Scy#endif 74275970Scy#ifndef _FILE_OFFSET_BITS 75275970Scy#define _FILE_OFFSET_BITS 0 76275970Scy#endif 77275970Scy#ifndef off64_t 78275970Scy#define off64_t ev_int64_t 79275970Scy#endif 80275970Scy 81275970Scy#include <zlib.h> 82275970Scy 83275970Scystatic int infilter_calls; 84275970Scystatic int outfilter_calls; 85275970Scystatic int readcb_finished; 86275970Scystatic int writecb_finished; 87275970Scystatic int errorcb_invoked; 88275970Scy 89275970Scy/* 90275970Scy * Zlib filters 91275970Scy */ 92275970Scy 93275970Scystatic void 94275970Scyzlib_deflate_free(void *ctx) 95275970Scy{ 96275970Scy z_streamp p = ctx; 97275970Scy 98275970Scy assert(deflateEnd(p) == Z_OK); 99282408Scy mm_free(p); 100275970Scy} 101275970Scy 102275970Scystatic void 103275970Scyzlib_inflate_free(void *ctx) 104275970Scy{ 105275970Scy z_streamp p = ctx; 106275970Scy 107275970Scy assert(inflateEnd(p) == Z_OK); 108282408Scy mm_free(p); 109275970Scy} 110275970Scy 111275970Scystatic int 112275970Scygetstate(enum bufferevent_flush_mode state) 113275970Scy{ 114275970Scy switch (state) { 115275970Scy case BEV_FINISHED: 116275970Scy return Z_FINISH; 117275970Scy case BEV_FLUSH: 118275970Scy return Z_SYNC_FLUSH; 119275970Scy case BEV_NORMAL: 120275970Scy default: 121275970Scy return Z_NO_FLUSH; 122275970Scy } 123275970Scy} 124275970Scy 125275970Scy/* 126275970Scy * The input filter is triggered only on new input read from the network. 127275970Scy * That means all input data needs to be consumed or the filter needs to 128275970Scy * initiate its own triggering via a timeout. 129275970Scy */ 130275970Scystatic enum bufferevent_filter_result 131275970Scyzlib_input_filter(struct evbuffer *src, struct evbuffer *dst, 132275970Scy ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 133275970Scy{ 134275970Scy struct evbuffer_iovec v_in[1]; 135275970Scy struct evbuffer_iovec v_out[1]; 136275970Scy int nread, nwrite; 137275970Scy int res, n; 138275970Scy 139275970Scy z_streamp p = ctx; 140275970Scy 141275970Scy do { 142275970Scy /* let's do some decompression */ 143275970Scy n = evbuffer_peek(src, -1, NULL, v_in, 1); 144275970Scy if (n) { 145275970Scy p->avail_in = v_in[0].iov_len; 146275970Scy p->next_in = v_in[0].iov_base; 147275970Scy } else { 148275970Scy p->avail_in = 0; 149275970Scy p->next_in = 0; 150275970Scy } 151275970Scy 152275970Scy evbuffer_reserve_space(dst, 4096, v_out, 1); 153275970Scy p->next_out = v_out[0].iov_base; 154275970Scy p->avail_out = v_out[0].iov_len; 155275970Scy 156275970Scy /* we need to flush zlib if we got a flush */ 157275970Scy res = inflate(p, getstate(state)); 158275970Scy 159275970Scy /* let's figure out how much was compressed */ 160275970Scy nread = v_in[0].iov_len - p->avail_in; 161275970Scy nwrite = v_out[0].iov_len - p->avail_out; 162275970Scy 163275970Scy evbuffer_drain(src, nread); 164275970Scy v_out[0].iov_len = nwrite; 165275970Scy evbuffer_commit_space(dst, v_out, 1); 166275970Scy 167275970Scy if (res==Z_BUF_ERROR) { 168275970Scy /* We're out of space, or out of decodeable input. 169275970Scy Only if nwrite == 0 assume the latter. 170275970Scy */ 171275970Scy if (nwrite == 0) 172275970Scy return BEV_NEED_MORE; 173275970Scy } else { 174275970Scy assert(res == Z_OK || res == Z_STREAM_END); 175275970Scy } 176275970Scy 177275970Scy } while (evbuffer_get_length(src) > 0); 178275970Scy 179275970Scy ++infilter_calls; 180275970Scy 181275970Scy return (BEV_OK); 182275970Scy} 183275970Scy 184275970Scystatic enum bufferevent_filter_result 185275970Scyzlib_output_filter(struct evbuffer *src, struct evbuffer *dst, 186275970Scy ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 187275970Scy{ 188275970Scy struct evbuffer_iovec v_in[1]; 189275970Scy struct evbuffer_iovec v_out[1]; 190275970Scy int nread, nwrite; 191275970Scy int res, n; 192275970Scy 193275970Scy z_streamp p = ctx; 194275970Scy 195275970Scy do { 196275970Scy /* let's do some compression */ 197275970Scy n = evbuffer_peek(src, -1, NULL, v_in, 1); 198275970Scy if (n) { 199275970Scy p->avail_in = v_in[0].iov_len; 200275970Scy p->next_in = v_in[0].iov_base; 201275970Scy } else { 202275970Scy p->avail_in = 0; 203275970Scy p->next_in = 0; 204275970Scy } 205275970Scy 206275970Scy evbuffer_reserve_space(dst, 4096, v_out, 1); 207275970Scy p->next_out = v_out[0].iov_base; 208275970Scy p->avail_out = v_out[0].iov_len; 209275970Scy 210275970Scy /* we need to flush zlib if we got a flush */ 211275970Scy res = deflate(p, getstate(state)); 212275970Scy 213275970Scy /* let's figure out how much was decompressed */ 214275970Scy nread = v_in[0].iov_len - p->avail_in; 215275970Scy nwrite = v_out[0].iov_len - p->avail_out; 216275970Scy 217275970Scy evbuffer_drain(src, nread); 218275970Scy v_out[0].iov_len = nwrite; 219275970Scy evbuffer_commit_space(dst, v_out, 1); 220275970Scy 221275970Scy if (res==Z_BUF_ERROR) { 222275970Scy /* We're out of space, or out of decodeable input. 223275970Scy Only if nwrite == 0 assume the latter. 224275970Scy */ 225275970Scy if (nwrite == 0) 226275970Scy return BEV_NEED_MORE; 227275970Scy } else { 228275970Scy assert(res == Z_OK || res == Z_STREAM_END); 229275970Scy } 230275970Scy 231275970Scy } while (evbuffer_get_length(src) > 0); 232275970Scy 233275970Scy ++outfilter_calls; 234275970Scy 235275970Scy return (BEV_OK); 236275970Scy} 237275970Scy 238275970Scy/* 239275970Scy * simple bufferevent test (over transparent zlib treatment) 240275970Scy */ 241275970Scy 242275970Scystatic void 243275970Scyreadcb(struct bufferevent *bev, void *arg) 244275970Scy{ 245275970Scy if (evbuffer_get_length(bufferevent_get_input(bev)) == 8333) { 246275970Scy struct evbuffer *evbuf = evbuffer_new(); 247275970Scy assert(evbuf != NULL); 248275970Scy 249275970Scy /* gratuitous test of bufferevent_read_buffer */ 250275970Scy bufferevent_read_buffer(bev, evbuf); 251275970Scy 252275970Scy bufferevent_disable(bev, EV_READ); 253275970Scy 254275970Scy if (evbuffer_get_length(evbuf) == 8333) { 255275970Scy ++readcb_finished; 256275970Scy } 257275970Scy 258275970Scy evbuffer_free(evbuf); 259275970Scy } 260275970Scy} 261275970Scy 262275970Scystatic void 263275970Scywritecb(struct bufferevent *bev, void *arg) 264275970Scy{ 265275970Scy if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { 266275970Scy ++writecb_finished; 267275970Scy } 268275970Scy} 269275970Scy 270275970Scystatic void 271275970Scyerrorcb(struct bufferevent *bev, short what, void *arg) 272275970Scy{ 273275970Scy errorcb_invoked = 1; 274275970Scy} 275275970Scy 276275970Scyvoid 277275970Scytest_bufferevent_zlib(void *arg) 278275970Scy{ 279275970Scy struct bufferevent *bev1=NULL, *bev2=NULL; 280275970Scy char buffer[8333]; 281282408Scy z_stream *z_input, *z_output; 282275970Scy int i, r; 283275970Scy evutil_socket_t pair[2] = {-1, -1}; 284275970Scy (void)arg; 285275970Scy 286275970Scy infilter_calls = outfilter_calls = readcb_finished = writecb_finished 287275970Scy = errorcb_invoked = 0; 288275970Scy 289275970Scy if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { 290275970Scy tt_abort_perror("socketpair"); 291275970Scy } 292275970Scy 293275970Scy evutil_make_socket_nonblocking(pair[0]); 294275970Scy evutil_make_socket_nonblocking(pair[1]); 295275970Scy 296275970Scy bev1 = bufferevent_socket_new(NULL, pair[0], 0); 297275970Scy bev2 = bufferevent_socket_new(NULL, pair[1], 0); 298275970Scy 299282408Scy z_output = mm_calloc(sizeof(*z_output), 1); 300282408Scy r = deflateInit(z_output, Z_DEFAULT_COMPRESSION); 301275970Scy tt_int_op(r, ==, Z_OK); 302282408Scy z_input = mm_calloc(sizeof(*z_input), 1); 303282408Scy r = inflateInit(z_input); 304275970Scy tt_int_op(r, ==, Z_OK); 305275970Scy 306275970Scy /* initialize filters */ 307275970Scy bev1 = bufferevent_filter_new(bev1, NULL, zlib_output_filter, 308282408Scy BEV_OPT_CLOSE_ON_FREE, zlib_deflate_free, z_output); 309275970Scy bev2 = bufferevent_filter_new(bev2, zlib_input_filter, 310282408Scy NULL, BEV_OPT_CLOSE_ON_FREE, zlib_inflate_free, z_input); 311275970Scy bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL); 312275970Scy bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); 313275970Scy 314275970Scy bufferevent_disable(bev1, EV_READ); 315275970Scy bufferevent_enable(bev1, EV_WRITE); 316275970Scy 317275970Scy bufferevent_enable(bev2, EV_READ); 318275970Scy 319275970Scy for (i = 0; i < (int)sizeof(buffer); i++) 320275970Scy buffer[i] = i; 321275970Scy 322275970Scy /* break it up into multiple buffer chains */ 323275970Scy bufferevent_write(bev1, buffer, 1800); 324275970Scy bufferevent_write(bev1, buffer + 1800, sizeof(buffer) - 1800); 325275970Scy 326275970Scy /* we are done writing - we need to flush everything */ 327275970Scy bufferevent_flush(bev1, EV_WRITE, BEV_FINISHED); 328275970Scy 329275970Scy event_dispatch(); 330275970Scy 331275970Scy tt_want(infilter_calls); 332275970Scy tt_want(outfilter_calls); 333275970Scy tt_want(readcb_finished); 334275970Scy tt_want(writecb_finished); 335275970Scy tt_want(!errorcb_invoked); 336275970Scy 337275970Scy test_ok = 1; 338275970Scyend: 339275970Scy if (bev1) 340275970Scy bufferevent_free(bev1); 341275970Scy if (bev2) 342275970Scy bufferevent_free(bev2); 343275970Scy 344275970Scy if (pair[0] >= 0) 345275970Scy evutil_closesocket(pair[0]); 346275970Scy if (pair[1] >= 0) 347275970Scy evutil_closesocket(pair[1]); 348275970Scy} 349