annotate src/io/rx_inflate.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
rev   line source
paulo@0 1 /*
paulo@0 2 * $Id: rx_inflate.c,v 1.10 2004/04/05 07:56:54 hipnod Exp $
paulo@0 3 *
paulo@0 4 * Copyright (C) 2003 giFT project (gift.sourceforge.net)
paulo@0 5 *
paulo@0 6 * This program is free software; you can redistribute it and/or modify it
paulo@0 7 * under the terms of the GNU General Public License as published by the
paulo@0 8 * Free Software Foundation; either version 2, or (at your option) any
paulo@0 9 * later version.
paulo@0 10 *
paulo@0 11 * This program is distributed in the hope that it will be useful, but
paulo@0 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
paulo@0 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
paulo@0 14 * General Public License for more details.
paulo@0 15 */
paulo@0 16
paulo@0 17 #include "gt_gnutella.h"
paulo@0 18
paulo@0 19 #include "rx_stack.h"
paulo@0 20 #include "rx_layer.h"
paulo@0 21
paulo@0 22 #include <zlib.h>
paulo@0 23
paulo@0 24 /*****************************************************************************/
paulo@0 25
paulo@0 26 /* this is small for testing purposes */
paulo@0 27 #define RX_INFLATE_BUFSIZE 256
paulo@0 28
paulo@0 29 #define RX_INFLATE(rx) \
paulo@0 30 ((struct rx_inflate *) (((rx)->udata)))
paulo@0 31
paulo@0 32 struct rx_inflate
paulo@0 33 {
paulo@0 34 z_stream z;
paulo@0 35 BOOL init_done;
paulo@0 36 };
paulo@0 37
paulo@0 38 /*****************************************************************************/
paulo@0 39
paulo@0 40 static BOOL rx_inflate_init (struct rx_layer *rx, void *udata)
paulo@0 41 {
paulo@0 42 struct rx_inflate *rx_inflate;
paulo@0 43
paulo@0 44 if (!(rx_inflate = NEW (struct rx_inflate)))
paulo@0 45 return FALSE;
paulo@0 46
paulo@0 47 /* inflateInit() may touch these variables */
paulo@0 48 rx_inflate->z.zalloc = Z_NULL;
paulo@0 49 rx_inflate->z.zfree = Z_NULL;
paulo@0 50 rx_inflate->z.opaque = Z_NULL;
paulo@0 51 rx_inflate->z.next_in = Z_NULL;
paulo@0 52 rx_inflate->z.avail_in = 0;
paulo@0 53
paulo@0 54 if (inflateInit (&rx_inflate->z) != Z_OK)
paulo@0 55 {
paulo@0 56 gt_rx_stack_abort (rx->stack);
paulo@0 57 return FALSE;
paulo@0 58 }
paulo@0 59
paulo@0 60 rx->udata = rx_inflate;
paulo@0 61
paulo@0 62 rx_inflate->init_done = TRUE;
paulo@0 63
paulo@0 64 return TRUE;
paulo@0 65 }
paulo@0 66
paulo@0 67 static void rx_inflate_destroy (struct rx_layer *rx)
paulo@0 68 {
paulo@0 69 struct rx_inflate *rx_inflate = RX_INFLATE(rx);
paulo@0 70
paulo@0 71 /*
paulo@0 72 * We don't check the error here, there could very well be leftover data
paulo@0 73 * and it would be annoying to print a message every time.
paulo@0 74 */
paulo@0 75 inflateEnd (&rx_inflate->z);
paulo@0 76 rx_inflate->init_done = FALSE;
paulo@0 77
paulo@0 78 FREE (rx_inflate);
paulo@0 79 }
paulo@0 80
paulo@0 81 static void rx_inflate_enable (struct rx_layer *rx)
paulo@0 82 {
paulo@0 83 /* nothing -- we only process data when it comes towards us */
paulo@0 84 }
paulo@0 85
paulo@0 86 static void rx_inflate_disable (struct rx_layer *rx)
paulo@0 87 {
paulo@0 88 /* nothing */
paulo@0 89 }
paulo@0 90
paulo@0 91 /*
paulo@0 92 * Handle the data from the lower layer, decompress it, and pass
paulo@0 93 * it to the upper layer.
paulo@0 94 */
paulo@0 95 static struct io_buf *read_buf (struct rx_layer *rx, struct io_buf *io_buf)
paulo@0 96 {
paulo@0 97 struct rx_inflate *rx_inflate = RX_INFLATE(rx);
paulo@0 98 struct io_buf *out_msg;
paulo@0 99 z_streamp inz;
paulo@0 100 int ret;
paulo@0 101 size_t uncompressed_size;
paulo@0 102 size_t compressed_read;
paulo@0 103 size_t out_size = RX_INFLATE_BUFSIZE;
paulo@0 104 size_t avail;
paulo@0 105 static size_t running_cnt = 0;
paulo@0 106 static int msg_count = 0;
paulo@0 107
paulo@0 108 avail = io_buf_read_avail (io_buf);
paulo@0 109
paulo@0 110 if (avail == 0)
paulo@0 111 return NULL;
paulo@0 112
paulo@0 113 if (!(out_msg = io_buf_new (out_size)))
paulo@0 114 {
paulo@0 115 GT->dbg (GT, "couldn't allocate memory for recv buf");
paulo@0 116 gt_rx_stack_abort (rx->stack);
paulo@0 117 return NULL;
paulo@0 118 }
paulo@0 119
paulo@0 120 assert (rx_inflate->init_done);
paulo@0 121 inz = &rx_inflate->z;
paulo@0 122
paulo@0 123 inz->next_in = io_buf_read_ptr (io_buf);
paulo@0 124 inz->avail_in = avail;
paulo@0 125 inz->next_out = io_buf_write_ptr (out_msg);
paulo@0 126 inz->avail_out = out_size;
paulo@0 127
paulo@0 128 ret = inflate (inz, Z_SYNC_FLUSH);
paulo@0 129
paulo@0 130 if (ret != Z_OK)
paulo@0 131 {
paulo@0 132 if (IO_DEBUG)
paulo@0 133 GT->dbg (GT, "zlib recv error: %d", ret);
paulo@0 134
paulo@0 135 gt_rx_stack_abort (rx->stack);
paulo@0 136 io_buf_free (out_msg);
paulo@0 137 return NULL;
paulo@0 138 }
paulo@0 139
paulo@0 140 uncompressed_size = out_size - inz->avail_out;
paulo@0 141 compressed_read = avail - inz->avail_in;
paulo@0 142
paulo@0 143 running_cnt += uncompressed_size;
paulo@0 144 if (IO_DEBUG && ++msg_count % 50 == 0)
paulo@0 145 {
paulo@0 146 GT->dbg (GT, "uncompressed %u bytes", running_cnt);
paulo@0 147 running_cnt = 0;
paulo@0 148 }
paulo@0 149
paulo@0 150 /* add the bytes we read to the new messge */
paulo@0 151 io_buf_push (out_msg, uncompressed_size);
paulo@0 152
paulo@0 153 /* pop the old bytes we read off the incoming message */
paulo@0 154 io_buf_pop (io_buf, compressed_read);
paulo@0 155
paulo@0 156 return out_msg;
paulo@0 157 }
paulo@0 158
paulo@0 159 /*
paulo@0 160 * Parse the data into buffers, and send it to the upper layers. packets to
paulo@0 161 */
paulo@0 162 static void rx_inflate_recv (struct rx_layer *rx, struct io_buf *io_buf)
paulo@0 163 {
paulo@0 164 struct io_buf *msg;
paulo@0 165
paulo@0 166 while (rx->enabled && (msg = read_buf (rx, io_buf)))
paulo@0 167 {
paulo@0 168 assert (msg != NULL);
paulo@0 169 gt_rx_layer_recv (rx, msg);
paulo@0 170
paulo@0 171 /*
paulo@0 172 * NOTE: gt_rx_layer_recv() may abort the stack here... there's not much
paulo@0 173 * we can do about that, but in practice that doesn't happen and we
paulo@0 174 * won't access freed memory because the stack doesn't get freed until
paulo@0 175 * the lowest rx layer is notified of the abort...pretty hacky.
paulo@0 176 */
paulo@0 177 }
paulo@0 178
paulo@0 179 /* we have to free the buffer */
paulo@0 180 io_buf_free (io_buf);
paulo@0 181 }
paulo@0 182
paulo@0 183 /*****************************************************************************/
paulo@0 184
paulo@0 185 struct rx_layer_ops gt_rx_inflate_ops =
paulo@0 186 {
paulo@0 187 rx_inflate_init,
paulo@0 188 rx_inflate_destroy,
paulo@0 189 rx_inflate_enable,
paulo@0 190 rx_inflate_disable,
paulo@0 191 rx_inflate_recv,
paulo@0 192 };