Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/io/rx_inflate.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,192 @@ 1.4 +/* 1.5 + * $Id: rx_inflate.c,v 1.10 2004/04/05 07:56:54 hipnod Exp $ 1.6 + * 1.7 + * Copyright (C) 2003 giFT project (gift.sourceforge.net) 1.8 + * 1.9 + * This program is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License as published by the 1.11 + * Free Software Foundation; either version 2, or (at your option) any 1.12 + * later version. 1.13 + * 1.14 + * This program is distributed in the hope that it will be useful, but 1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + * General Public License for more details. 1.18 + */ 1.19 + 1.20 +#include "gt_gnutella.h" 1.21 + 1.22 +#include "rx_stack.h" 1.23 +#include "rx_layer.h" 1.24 + 1.25 +#include <zlib.h> 1.26 + 1.27 +/*****************************************************************************/ 1.28 + 1.29 +/* this is small for testing purposes */ 1.30 +#define RX_INFLATE_BUFSIZE 256 1.31 + 1.32 +#define RX_INFLATE(rx) \ 1.33 + ((struct rx_inflate *) (((rx)->udata))) 1.34 + 1.35 +struct rx_inflate 1.36 +{ 1.37 + z_stream z; 1.38 + BOOL init_done; 1.39 +}; 1.40 + 1.41 +/*****************************************************************************/ 1.42 + 1.43 +static BOOL rx_inflate_init (struct rx_layer *rx, void *udata) 1.44 +{ 1.45 + struct rx_inflate *rx_inflate; 1.46 + 1.47 + if (!(rx_inflate = NEW (struct rx_inflate))) 1.48 + return FALSE; 1.49 + 1.50 + /* inflateInit() may touch these variables */ 1.51 + rx_inflate->z.zalloc = Z_NULL; 1.52 + rx_inflate->z.zfree = Z_NULL; 1.53 + rx_inflate->z.opaque = Z_NULL; 1.54 + rx_inflate->z.next_in = Z_NULL; 1.55 + rx_inflate->z.avail_in = 0; 1.56 + 1.57 + if (inflateInit (&rx_inflate->z) != Z_OK) 1.58 + { 1.59 + gt_rx_stack_abort (rx->stack); 1.60 + return FALSE; 1.61 + } 1.62 + 1.63 + rx->udata = rx_inflate; 1.64 + 1.65 + rx_inflate->init_done = TRUE; 1.66 + 1.67 + return TRUE; 1.68 +} 1.69 + 1.70 +static void rx_inflate_destroy (struct rx_layer *rx) 1.71 +{ 1.72 + struct rx_inflate *rx_inflate = RX_INFLATE(rx); 1.73 + 1.74 + /* 1.75 + * We don't check the error here, there could very well be leftover data 1.76 + * and it would be annoying to print a message every time. 1.77 + */ 1.78 + inflateEnd (&rx_inflate->z); 1.79 + rx_inflate->init_done = FALSE; 1.80 + 1.81 + FREE (rx_inflate); 1.82 +} 1.83 + 1.84 +static void rx_inflate_enable (struct rx_layer *rx) 1.85 +{ 1.86 + /* nothing -- we only process data when it comes towards us */ 1.87 +} 1.88 + 1.89 +static void rx_inflate_disable (struct rx_layer *rx) 1.90 +{ 1.91 + /* nothing */ 1.92 +} 1.93 + 1.94 +/* 1.95 + * Handle the data from the lower layer, decompress it, and pass 1.96 + * it to the upper layer. 1.97 + */ 1.98 +static struct io_buf *read_buf (struct rx_layer *rx, struct io_buf *io_buf) 1.99 +{ 1.100 + struct rx_inflate *rx_inflate = RX_INFLATE(rx); 1.101 + struct io_buf *out_msg; 1.102 + z_streamp inz; 1.103 + int ret; 1.104 + size_t uncompressed_size; 1.105 + size_t compressed_read; 1.106 + size_t out_size = RX_INFLATE_BUFSIZE; 1.107 + size_t avail; 1.108 + static size_t running_cnt = 0; 1.109 + static int msg_count = 0; 1.110 + 1.111 + avail = io_buf_read_avail (io_buf); 1.112 + 1.113 + if (avail == 0) 1.114 + return NULL; 1.115 + 1.116 + if (!(out_msg = io_buf_new (out_size))) 1.117 + { 1.118 + GT->dbg (GT, "couldn't allocate memory for recv buf"); 1.119 + gt_rx_stack_abort (rx->stack); 1.120 + return NULL; 1.121 + } 1.122 + 1.123 + assert (rx_inflate->init_done); 1.124 + inz = &rx_inflate->z; 1.125 + 1.126 + inz->next_in = io_buf_read_ptr (io_buf); 1.127 + inz->avail_in = avail; 1.128 + inz->next_out = io_buf_write_ptr (out_msg); 1.129 + inz->avail_out = out_size; 1.130 + 1.131 + ret = inflate (inz, Z_SYNC_FLUSH); 1.132 + 1.133 + if (ret != Z_OK) 1.134 + { 1.135 + if (IO_DEBUG) 1.136 + GT->dbg (GT, "zlib recv error: %d", ret); 1.137 + 1.138 + gt_rx_stack_abort (rx->stack); 1.139 + io_buf_free (out_msg); 1.140 + return NULL; 1.141 + } 1.142 + 1.143 + uncompressed_size = out_size - inz->avail_out; 1.144 + compressed_read = avail - inz->avail_in; 1.145 + 1.146 + running_cnt += uncompressed_size; 1.147 + if (IO_DEBUG && ++msg_count % 50 == 0) 1.148 + { 1.149 + GT->dbg (GT, "uncompressed %u bytes", running_cnt); 1.150 + running_cnt = 0; 1.151 + } 1.152 + 1.153 + /* add the bytes we read to the new messge */ 1.154 + io_buf_push (out_msg, uncompressed_size); 1.155 + 1.156 + /* pop the old bytes we read off the incoming message */ 1.157 + io_buf_pop (io_buf, compressed_read); 1.158 + 1.159 + return out_msg; 1.160 +} 1.161 + 1.162 +/* 1.163 + * Parse the data into buffers, and send it to the upper layers. packets to 1.164 + */ 1.165 +static void rx_inflate_recv (struct rx_layer *rx, struct io_buf *io_buf) 1.166 +{ 1.167 + struct io_buf *msg; 1.168 + 1.169 + while (rx->enabled && (msg = read_buf (rx, io_buf))) 1.170 + { 1.171 + assert (msg != NULL); 1.172 + gt_rx_layer_recv (rx, msg); 1.173 + 1.174 + /* 1.175 + * NOTE: gt_rx_layer_recv() may abort the stack here... there's not much 1.176 + * we can do about that, but in practice that doesn't happen and we 1.177 + * won't access freed memory because the stack doesn't get freed until 1.178 + * the lowest rx layer is notified of the abort...pretty hacky. 1.179 + */ 1.180 + } 1.181 + 1.182 + /* we have to free the buffer */ 1.183 + io_buf_free (io_buf); 1.184 +} 1.185 + 1.186 +/*****************************************************************************/ 1.187 + 1.188 +struct rx_layer_ops gt_rx_inflate_ops = 1.189 +{ 1.190 + rx_inflate_init, 1.191 + rx_inflate_destroy, 1.192 + rx_inflate_enable, 1.193 + rx_inflate_disable, 1.194 + rx_inflate_recv, 1.195 +};