]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/conn-zip.c
- New source files "conn-zip.c" and "conn-zip.h".
[ngircd-alex.git] / src / ngircd / conn-zip.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  *
11  * Connection compression using ZLIB
12  */
13
14
15 #include "portab.h"
16
17 #define __conn_zip_c__
18
19
20 #ifdef USE_ZLIB
21
22 static char UNUSED id[] = "$Id: conn-zip.c,v 1.1 2002/12/30 16:07:23 alex Exp $";
23
24 #include "imp.h"
25 #include <assert.h>
26 #include <string.h>
27 #include <zlib.h>
28
29 #include "conn.h"
30 #include "log.h"
31
32 #include "exp.h"
33 #include "conn-zip.h"
34
35
36 GLOBAL BOOLEAN
37 Zip_InitConn( CONN_ID Idx )
38 {
39         /* Kompression fuer Link initialisieren */
40
41         assert( Idx > NONE );
42
43         My_Connections[Idx].zip.in.avail_in = 0;
44         My_Connections[Idx].zip.in.total_in = 0;
45         My_Connections[Idx].zip.in.total_out = 0;
46         My_Connections[Idx].zip.in.zalloc = NULL;
47         My_Connections[Idx].zip.in.zfree = NULL;
48         My_Connections[Idx].zip.in.data_type = Z_ASCII;
49
50         if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK )
51         {
52                 /* Fehler! */
53                 Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx );
54                 return FALSE;
55         }
56
57         My_Connections[Idx].zip.out.total_in = 0;
58         My_Connections[Idx].zip.out.total_in = 0;
59         My_Connections[Idx].zip.out.zalloc = NULL;
60         My_Connections[Idx].zip.out.zfree = NULL;
61         My_Connections[Idx].zip.out.data_type = Z_ASCII;
62
63         if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK )
64         {
65                 /* Fehler! */
66                 Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx );
67                 return FALSE;
68         }
69
70         My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in;
71         My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out;
72
73         Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx );
74         Conn_SetOption( Idx, CONN_ZIP );
75
76         return TRUE;
77 } /* Zip_InitConn */
78
79
80 GLOBAL BOOLEAN
81 Zip_Buffer( CONN_ID Idx, CHAR *Data, INT Len )
82 {
83         /* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
84         * Es wird TRUE bei Erfolg, sonst FALSE geliefert. */
85
86         assert( Idx > NONE );
87         assert( Data != NULL );
88         assert( Len > 0 );
89
90         /* Ist noch Platz im Kompressions-Puffer? */
91         if( ZWRITEBUFFER_LEN - My_Connections[Idx].zip.wdatalen < Len + 50 )
92         {
93                 /* Nein! Puffer zunaechst leeren ...*/
94                 if( ! Zip_Flush( Idx )) return FALSE;
95         }
96
97         /* Daten kopieren */
98         memmove( My_Connections[Idx].zip.wbuf + My_Connections[Idx].zip.wdatalen, Data, Len );
99         My_Connections[Idx].zip.wdatalen += Len;
100
101         return TRUE;
102 } /* Zip_Buffer */
103
104
105 GLOBAL BOOLEAN
106 Zip_Flush( CONN_ID Idx )
107 {
108         /* Daten komprimieren und in Schreibpuffer kopieren.
109         * Es wird TRUE bei Erfolg, sonst FALSE geliefert. */
110
111         INT result, out_len;
112         z_stream *out;
113
114         out = &My_Connections[Idx].zip.out;
115
116         out->next_in = My_Connections[Idx].zip.wbuf;
117         out->avail_in = My_Connections[Idx].zip.wdatalen;
118         out->next_out = My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen;
119         out->avail_out = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen;
120
121         result = deflate( out, Z_SYNC_FLUSH );
122         if(( result != Z_OK ) || ( out->avail_in > 0 ))
123         {
124                 Log( LOG_ALERT, "Compression error: code %d!?", result );
125                 Conn_Close( Idx, "Compression error!", NULL, FALSE );
126                 return FALSE;
127         }
128
129         out_len = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - out->avail_out;
130         My_Connections[Idx].wdatalen += out_len;
131         My_Connections[Idx].bytes_out += out_len;
132         My_Connections[Idx].zip.bytes_out += My_Connections[Idx].zip.wdatalen;
133         My_Connections[Idx].zip.wdatalen = 0;
134
135         return TRUE;
136 } /* Zip_Flush */
137
138
139 GLOBAL BOOLEAN
140 Unzip_Buffer( CONN_ID Idx )
141 {
142         /* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern
143         * wird FALSE geliefert, ansonsten TRUE. Der Fall, dass keine
144         * Daten mehr zu entpacken sind, ist _kein_ Fehler! */
145
146         INT result, in_len, out_len;
147         z_stream *in;
148
149         assert( Idx > NONE );
150
151         if( My_Connections[Idx].zip.rdatalen <= 0 ) return TRUE;
152
153         in = &My_Connections[Idx].zip.in;
154
155         in->next_in = My_Connections[Idx].zip.rbuf;
156         in->avail_in = My_Connections[Idx].zip.rdatalen;
157         in->next_out = My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen;
158         in->avail_out = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1;
159
160         result = inflate( in, Z_SYNC_FLUSH );
161         if( result != Z_OK )
162         {
163                 Log( LOG_ALERT, "Decompression error: code %d (ni=%d, ai=%d, no=%d, ao=%d)!?", result, in->next_in, in->avail_in, in->next_out, in->avail_out );
164                 Conn_Close( Idx, "Decompression error!", NULL, FALSE );
165                 return FALSE;
166         }
167
168         in_len = My_Connections[Idx].zip.rdatalen - in->avail_in;
169         out_len = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1 - in->avail_out;
170         My_Connections[Idx].rdatalen += out_len;
171
172         if( in->avail_in > 0 )
173         {
174                 /* es konnten nicht alle Daten entpackt werden, vermutlich war
175                 * im Ziel-Puffer kein Platz mehr. Umkopieren ... */
176                 My_Connections[Idx].zip.rdatalen -= in_len;
177                 memmove( My_Connections[Idx].zip.rbuf, My_Connections[Idx].zip.rbuf + in_len, My_Connections[Idx].zip.rdatalen );
178         }
179         else My_Connections[Idx].zip.rdatalen = 0;
180         My_Connections[Idx].zip.bytes_in += out_len;
181
182         return TRUE;
183 } /* Unzip_Buffer */
184
185
186 GLOBAL LONG
187 Zip_SendBytes( CONN_ID Idx )
188 {
189         /* Anzahl gesendeter Bytes (komprimiert!) liefern */
190
191         assert( Idx > NONE );
192         return My_Connections[Idx].zip.bytes_out;
193 } /* Zip_SendBytes */
194
195
196 GLOBAL LONG
197 Zip_RecvBytes( CONN_ID Idx )
198 {
199         /* Anzahl gesendeter Bytes (komprimiert!) liefern */
200
201         assert( Idx > NONE );
202         return My_Connections[Idx].zip.bytes_in;
203 } /* Zip_RecvBytes */
204
205
206 #endif
207
208
209 /* -eof- */