Blame


1 e68cdf30 2003-12-30 alex /*
2 e68cdf30 2003-12-30 alex * ngIRCd -- The Next Generation IRC Daemon
3 255edf7e 2007-05-17 alex * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
4 e68cdf30 2003-12-30 alex *
5 e68cdf30 2003-12-30 alex * This program is free software; you can redistribute it and/or modify
6 e68cdf30 2003-12-30 alex * it under the terms of the GNU General Public License as published by
7 e68cdf30 2003-12-30 alex * the Free Software Foundation; either version 2 of the License, or
8 e68cdf30 2003-12-30 alex * (at your option) any later version.
9 e68cdf30 2003-12-30 alex * Please read the file COPYING, README and AUTHORS for more information.
10 e68cdf30 2003-12-30 alex *
11 e68cdf30 2003-12-30 alex * Connection compression using ZLIB
12 e68cdf30 2003-12-30 alex */
13 e68cdf30 2003-12-30 alex
14 e68cdf30 2003-12-30 alex
15 e68cdf30 2003-12-30 alex #include "portab.h"
16 e68cdf30 2003-12-30 alex
17 b77dae34 2003-12-30 alex #define CONN_MODULE
18 e68cdf30 2003-12-30 alex
19 e68cdf30 2003-12-30 alex
20 c40592d2 2003-12-26 alex #ifdef ZLIB
21 e68cdf30 2003-12-30 alex
22 0d5fc770 2006-07-23 alex /* enable more zlib related debug messages: */
23 0d5fc770 2006-07-23 alex /* #define DEBUG_ZLIB */
24 e68cdf30 2003-12-30 alex
25 255edf7e 2007-05-17 alex static char UNUSED id[] = "$Id: conn-zip.c,v 1.16 2007/05/17 23:34:24 alex Exp $";
26 0d5fc770 2006-07-23 alex
27 e68cdf30 2003-12-30 alex #include "imp.h"
28 e68cdf30 2003-12-30 alex #include <assert.h>
29 e68cdf30 2003-12-30 alex #include <string.h>
30 e68cdf30 2003-12-30 alex #include <zlib.h>
31 e68cdf30 2003-12-30 alex
32 e68cdf30 2003-12-30 alex #include "conn.h"
33 b77dae34 2003-12-30 alex #include "conn-func.h"
34 e68cdf30 2003-12-30 alex #include "log.h"
35 e68cdf30 2003-12-30 alex
36 60ae9c82 2005-07-07 fw #include "array.h"
37 e68cdf30 2003-12-30 alex #include "exp.h"
38 e68cdf30 2003-12-30 alex #include "conn-zip.h"
39 e68cdf30 2003-12-30 alex
40 e68cdf30 2003-12-30 alex
41 8adff592 2005-03-19 fw GLOBAL bool
42 e68cdf30 2003-12-30 alex Zip_InitConn( CONN_ID Idx )
43 e68cdf30 2003-12-30 alex {
44 e68cdf30 2003-12-30 alex /* Kompression fuer Link initialisieren */
45 e68cdf30 2003-12-30 alex
46 e68cdf30 2003-12-30 alex assert( Idx > NONE );
47 e68cdf30 2003-12-30 alex
48 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.avail_in = 0;
49 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.total_in = 0;
50 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.total_out = 0;
51 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.zalloc = NULL;
52 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.zfree = NULL;
53 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.in.data_type = Z_ASCII;
54 e68cdf30 2003-12-30 alex
55 e68cdf30 2003-12-30 alex if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK )
56 e68cdf30 2003-12-30 alex {
57 e68cdf30 2003-12-30 alex /* Fehler! */
58 e68cdf30 2003-12-30 alex Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx );
59 8adff592 2005-03-19 fw return false;
60 e68cdf30 2003-12-30 alex }
61 e68cdf30 2003-12-30 alex
62 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.out.total_in = 0;
63 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.out.total_in = 0;
64 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.out.zalloc = NULL;
65 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.out.zfree = NULL;
66 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.out.data_type = Z_ASCII;
67 e68cdf30 2003-12-30 alex
68 e68cdf30 2003-12-30 alex if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK )
69 e68cdf30 2003-12-30 alex {
70 e68cdf30 2003-12-30 alex /* Fehler! */
71 e68cdf30 2003-12-30 alex Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx );
72 8adff592 2005-03-19 fw return false;
73 e68cdf30 2003-12-30 alex }
74 e68cdf30 2003-12-30 alex
75 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in;
76 e68cdf30 2003-12-30 alex My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out;
77 e68cdf30 2003-12-30 alex
78 e68cdf30 2003-12-30 alex Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx );
79 7daa7fb2 2005-04-25 fw Conn_OPTION_ADD( &My_Connections[Idx], CONN_ZIP );
80 e68cdf30 2003-12-30 alex
81 8adff592 2005-03-19 fw return true;
82 e68cdf30 2003-12-30 alex } /* Zip_InitConn */
83 e68cdf30 2003-12-30 alex
84 e68cdf30 2003-12-30 alex
85 255edf7e 2007-05-17 alex /**
86 255edf7e 2007-05-17 alex * Copy data to the compression buffer of a connection. We do collect
87 255edf7e 2007-05-17 alex * some data there until it's full so that we can achieve better
88 255edf7e 2007-05-17 alex * compression ratios.
89 255edf7e 2007-05-17 alex * If the (pre-)compression buffer is full, we try to flush it ("actually
90 255edf7e 2007-05-17 alex * compress some data") and to add the new (uncompressed) data afterwards.
91 255edf7e 2007-05-17 alex * @param Idx Connection handle.
92 255edf7e 2007-05-17 alex * @param Data Pointer to the data.
93 255edf7e 2007-05-17 alex * @param Len Length of the data to add.
94 255edf7e 2007-05-17 alex * @return true on success, false otherwise. */
95 8adff592 2005-03-19 fw GLOBAL bool
96 dd3a3bc6 2006-05-10 alex Zip_Buffer( CONN_ID Idx, char *Data, size_t Len )
97 e68cdf30 2003-12-30 alex {
98 09416f36 2007-05-09 fw size_t buflen;
99 e68cdf30 2003-12-30 alex
100 e68cdf30 2003-12-30 alex assert( Idx > NONE );
101 e68cdf30 2003-12-30 alex assert( Data != NULL );
102 e68cdf30 2003-12-30 alex assert( Len > 0 );
103 e68cdf30 2003-12-30 alex
104 09416f36 2007-05-09 fw buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
105 255edf7e 2007-05-17 alex if (buflen + Len >= WRITEBUFFER_SLINK_LEN) {
106 60ae9c82 2005-07-07 fw /* compression buffer is full, flush */
107 8adff592 2005-03-19 fw if( ! Zip_Flush( Idx )) return false;
108 e68cdf30 2003-12-30 alex }
109 e68cdf30 2003-12-30 alex
110 09416f36 2007-05-09 fw /* check again; if zip buf is still too large do not append data:
111 09416f36 2007-05-09 fw * otherwise the zip wbuf would grow too large */
112 09416f36 2007-05-09 fw buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
113 255edf7e 2007-05-17 alex if (buflen + Len >= WRITEBUFFER_SLINK_LEN)
114 09416f36 2007-05-09 fw return false;
115 255edf7e 2007-05-17 alex
116 dd3a3bc6 2006-05-10 alex return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len);
117 e68cdf30 2003-12-30 alex } /* Zip_Buffer */
118 e68cdf30 2003-12-30 alex
119 e68cdf30 2003-12-30 alex
120 44afe042 2007-05-17 alex /**
121 44afe042 2007-05-17 alex * Compress data in ZIP buffer and move result to the write buffer of
122 44afe042 2007-05-17 alex * the connection.
123 44afe042 2007-05-17 alex * @param Idx Connection handle.
124 44afe042 2007-05-17 alex * @retrun true on success, false otherwise.
125 44afe042 2007-05-17 alex */
126 8adff592 2005-03-19 fw GLOBAL bool
127 e68cdf30 2003-12-30 alex Zip_Flush( CONN_ID Idx )
128 e68cdf30 2003-12-30 alex {
129 60ae9c82 2005-07-07 fw int result;
130 255edf7e 2007-05-17 alex unsigned char zipbuf[WRITEBUFFER_SLINK_LEN];
131 dd3a3bc6 2006-05-10 alex int zipbuf_used = 0;
132 e68cdf30 2003-12-30 alex z_stream *out;
133 e68cdf30 2003-12-30 alex
134 e68cdf30 2003-12-30 alex out = &My_Connections[Idx].zip.out;
135 e68cdf30 2003-12-30 alex
136 dd3a3bc6 2006-05-10 alex out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf);
137 44afe042 2007-05-17 alex if (!out->avail_in)
138 44afe042 2007-05-17 alex return true; /* nothing to do. */
139 07d8da60 2007-05-17 fw
140 07d8da60 2007-05-17 fw out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
141 07d8da60 2007-05-17 fw assert(out->next_in != NULL);
142 60ae9c82 2005-07-07 fw
143 60ae9c82 2005-07-07 fw out->next_out = zipbuf;
144 dd3a3bc6 2006-05-10 alex out->avail_out = (uInt)sizeof zipbuf;
145 60ae9c82 2005-07-07 fw
146 0d5fc770 2006-07-23 alex #ifdef DEBUG_ZIP
147 0d5fc770 2006-07-23 alex Log(LOG_DEBUG, "out->avail_in %d, out->avail_out %d",
148 0d5fc770 2006-07-23 alex out->avail_in, out->avail_out);
149 0d5fc770 2006-07-23 alex #endif
150 e68cdf30 2003-12-30 alex result = deflate( out, Z_SYNC_FLUSH );
151 e68cdf30 2003-12-30 alex if(( result != Z_OK ) || ( out->avail_in > 0 ))
152 e68cdf30 2003-12-30 alex {
153 e68cdf30 2003-12-30 alex Log( LOG_ALERT, "Compression error: code %d!?", result );
154 8adff592 2005-03-19 fw Conn_Close( Idx, "Compression error!", NULL, false );
155 8adff592 2005-03-19 fw return false;
156 e68cdf30 2003-12-30 alex }
157 e68cdf30 2003-12-30 alex
158 44afe042 2007-05-17 alex if (out->avail_out <= 0) {
159 44afe042 2007-05-17 alex /* Not all data was compressed, because data became
160 44afe042 2007-05-17 alex * bigger while compressing it. */
161 44afe042 2007-05-17 alex Log (LOG_ALERT, "Compression error: buffer overvlow!?");
162 44afe042 2007-05-17 alex Conn_Close(Idx, "Compression error!", NULL, false);
163 44afe042 2007-05-17 alex return false;
164 44afe042 2007-05-17 alex }
165 44afe042 2007-05-17 alex
166 255edf7e 2007-05-17 alex assert(out->avail_out <= WRITEBUFFER_SLINK_LEN);
167 44afe042 2007-05-17 alex
168 255edf7e 2007-05-17 alex zipbuf_used = WRITEBUFFER_SLINK_LEN - out->avail_out;
169 0d5fc770 2006-07-23 alex #ifdef DEBUG_ZIP
170 1c14e2e0 2005-08-02 alex Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
171 0d5fc770 2006-07-23 alex #endif
172 dd3a3bc6 2006-05-10 alex if (!array_catb(&My_Connections[Idx].wbuf,
173 5930a291 2007-05-17 alex (char *)zipbuf, (size_t) zipbuf_used)) {
174 5930a291 2007-05-17 alex Log (LOG_ALERT, "Compression error: can't copy data!?");
175 5930a291 2007-05-17 alex Conn_Close(Idx, "Compression error!", NULL, false);
176 60ae9c82 2005-07-07 fw return false;
177 5930a291 2007-05-17 alex }
178 e68cdf30 2003-12-30 alex
179 60ae9c82 2005-07-07 fw My_Connections[Idx].bytes_out += zipbuf_used;
180 60ae9c82 2005-07-07 fw My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf);
181 60ae9c82 2005-07-07 fw array_trunc(&My_Connections[Idx].zip.wbuf);
182 60ae9c82 2005-07-07 fw
183 8adff592 2005-03-19 fw return true;
184 e68cdf30 2003-12-30 alex } /* Zip_Flush */
185 e68cdf30 2003-12-30 alex
186 e68cdf30 2003-12-30 alex
187 8adff592 2005-03-19 fw GLOBAL bool
188 e68cdf30 2003-12-30 alex Unzip_Buffer( CONN_ID Idx )
189 e68cdf30 2003-12-30 alex {
190 e68cdf30 2003-12-30 alex /* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern
191 8adff592 2005-03-19 fw * wird false geliefert, ansonsten true. Der Fall, dass keine
192 e68cdf30 2003-12-30 alex * Daten mehr zu entpacken sind, ist _kein_ Fehler! */
193 e68cdf30 2003-12-30 alex
194 60ae9c82 2005-07-07 fw int result;
195 60ae9c82 2005-07-07 fw unsigned char unzipbuf[READBUFFER_LEN];
196 dd3a3bc6 2006-05-10 alex int unzipbuf_used = 0;
197 60ae9c82 2005-07-07 fw unsigned int z_rdatalen;
198 60ae9c82 2005-07-07 fw unsigned int in_len;
199 60ae9c82 2005-07-07 fw
200 e68cdf30 2003-12-30 alex z_stream *in;
201 e68cdf30 2003-12-30 alex
202 e68cdf30 2003-12-30 alex assert( Idx > NONE );
203 e68cdf30 2003-12-30 alex
204 dd3a3bc6 2006-05-10 alex z_rdatalen = (unsigned int)array_bytes(&My_Connections[Idx].zip.rbuf);
205 60ae9c82 2005-07-07 fw if (z_rdatalen == 0)
206 60ae9c82 2005-07-07 fw return true;
207 e68cdf30 2003-12-30 alex
208 e68cdf30 2003-12-30 alex in = &My_Connections[Idx].zip.in;
209 07d8da60 2007-05-17 fw
210 60ae9c82 2005-07-07 fw in->next_in = array_start(&My_Connections[Idx].zip.rbuf);
211 07d8da60 2007-05-17 fw assert(in->next_in != NULL);
212 e68cdf30 2003-12-30 alex
213 60ae9c82 2005-07-07 fw in->avail_in = z_rdatalen;
214 60ae9c82 2005-07-07 fw in->next_out = unzipbuf;
215 dd3a3bc6 2006-05-10 alex in->avail_out = (uInt)sizeof unzipbuf;
216 e68cdf30 2003-12-30 alex
217 0d5fc770 2006-07-23 alex #ifdef DEBUG_ZIP
218 0d5fc770 2006-07-23 alex Log(LOG_DEBUG, "in->avail_in %d, in->avail_out %d",
219 0d5fc770 2006-07-23 alex in->avail_in, in->avail_out);
220 0d5fc770 2006-07-23 alex #endif
221 e68cdf30 2003-12-30 alex result = inflate( in, Z_SYNC_FLUSH );
222 e68cdf30 2003-12-30 alex if( result != Z_OK )
223 e68cdf30 2003-12-30 alex {
224 292c7bd4 2004-04-25 alex Log( LOG_ALERT, "Decompression error: %s (code=%d, ni=%d, ai=%d, no=%d, ao=%d)!?", in->msg, result, in->next_in, in->avail_in, in->next_out, in->avail_out );
225 8adff592 2005-03-19 fw Conn_Close( Idx, "Decompression error!", NULL, false );
226 8adff592 2005-03-19 fw return false;
227 e68cdf30 2003-12-30 alex }
228 e68cdf30 2003-12-30 alex
229 60ae9c82 2005-07-07 fw assert(z_rdatalen >= in->avail_in);
230 60ae9c82 2005-07-07 fw in_len = z_rdatalen - in->avail_in;
231 60ae9c82 2005-07-07 fw unzipbuf_used = READBUFFER_LEN - in->avail_out;
232 0d5fc770 2006-07-23 alex #ifdef DEBUG_ZIP
233 0d5fc770 2006-07-23 alex Log(LOG_DEBUG, "unzipbuf_used: %d - %d = %d", READBUFFER_LEN,
234 0d5fc770 2006-07-23 alex in->avail_out, unzipbuf_used);
235 0d5fc770 2006-07-23 alex #endif
236 60ae9c82 2005-07-07 fw assert(unzipbuf_used <= READBUFFER_LEN);
237 dd3a3bc6 2006-05-10 alex if (!array_catb(&My_Connections[Idx].rbuf, (char*) unzipbuf,
238 dd3a3bc6 2006-05-10 alex (size_t)unzipbuf_used))
239 60ae9c82 2005-07-07 fw return false;
240 e68cdf30 2003-12-30 alex
241 60ae9c82 2005-07-07 fw if( in->avail_in > 0 ) {
242 60ae9c82 2005-07-07 fw array_moveleft(&My_Connections[Idx].zip.rbuf, 1, in_len );
243 60ae9c82 2005-07-07 fw } else {
244 60ae9c82 2005-07-07 fw array_trunc( &My_Connections[Idx].zip.rbuf );
245 60ae9c82 2005-07-07 fw My_Connections[Idx].zip.bytes_in += unzipbuf_used;
246 e68cdf30 2003-12-30 alex }
247 e68cdf30 2003-12-30 alex
248 8adff592 2005-03-19 fw return true;
249 e68cdf30 2003-12-30 alex } /* Unzip_Buffer */
250 e68cdf30 2003-12-30 alex
251 e68cdf30 2003-12-30 alex
252 8adff592 2005-03-19 fw GLOBAL long
253 e68cdf30 2003-12-30 alex Zip_SendBytes( CONN_ID Idx )
254 e68cdf30 2003-12-30 alex {
255 e68cdf30 2003-12-30 alex /* Anzahl gesendeter Bytes (komprimiert!) liefern */
256 e68cdf30 2003-12-30 alex
257 e68cdf30 2003-12-30 alex assert( Idx > NONE );
258 e68cdf30 2003-12-30 alex return My_Connections[Idx].zip.bytes_out;
259 e68cdf30 2003-12-30 alex } /* Zip_SendBytes */
260 e68cdf30 2003-12-30 alex
261 e68cdf30 2003-12-30 alex
262 8adff592 2005-03-19 fw GLOBAL long
263 e68cdf30 2003-12-30 alex Zip_RecvBytes( CONN_ID Idx )
264 e68cdf30 2003-12-30 alex {
265 e68cdf30 2003-12-30 alex /* Anzahl gesendeter Bytes (komprimiert!) liefern */
266 e68cdf30 2003-12-30 alex
267 e68cdf30 2003-12-30 alex assert( Idx > NONE );
268 e68cdf30 2003-12-30 alex return My_Connections[Idx].zip.bytes_in;
269 e68cdf30 2003-12-30 alex } /* Zip_RecvBytes */
270 e68cdf30 2003-12-30 alex
271 e68cdf30 2003-12-30 alex
272 e68cdf30 2003-12-30 alex #endif
273 e68cdf30 2003-12-30 alex
274 e68cdf30 2003-12-30 alex
275 e68cdf30 2003-12-30 alex /* -eof- */