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