]> jfr.im git - irc.git/blame - software/ircd/www.irc.org/ftp/irc/org/irc2.11.2p3/ircd/s_zip.c
init
[irc.git] / software / ircd / www.irc.org / ftp / irc / org / irc2.11.2p3 / ircd / s_zip.c
CommitLineData
3bd189cb
JR
1/************************************************************************
2 * IRC - Internet Relay Chat, ircd/s_zip.c
3 * Copyright (C) 1996 Christophe Kalt
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 1, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef lint
21static const volatile char rcsid[] = "@(#)$Id: s_zip.c,v 1.12 2005/02/20 23:09:45 chopin Exp $";
22#endif
23
24#include "os.h"
25#include "s_defines.h"
26#define S_ZIP_C
27#include "s_externs.h"
28#undef S_ZIP_C
29
30#ifdef ZIP_LINKS
31
32/*
33** Important note:
34** The provided buffers for compression *MUST* be big
35** enough for any operation to complete.
36**
37** s_bsd.c current settings are that the biggest packet size is 16k
38** (but socket buffers are set to 8k..)
39*/
40
41/*
42** size of the buffer holding compressed data
43**
44** outgoing data:
45** must be enough to hold compressed data resulting of the compression
46** of up to ZIP_MAXIMUM bytes
47** incoming data:
48** must be enough to hold what was just read
49** (cptr->zip->inbuf should never hold more than ONE compression block.
50** The biggest block allowed for compression is ZIP_MAXIMUM bytes)
51*/
52#define ZIP_BUFFER_SIZE (MAX(ZIP_MAXIMUM, READBUF_SIZE))
53
54/*
55** size of the buffer where zlib puts compressed data
56** should be enough to hold uncompressed data resulting of the
57** uncompression of zipbuffer
58**
59** tests show that an average ratio is around 40%,
60** in some very particular cases, ratio can be VERY low, BUT:
61**
62** s_bsd.c/read_packet() is now smart enough to detect when uncompression
63** stopped because the buffer is too small, and calls dopacket() again
64** to finish the work (as many times as needed).
65*/
66#define UNZIP_BUFFER_SIZE 4*ZIP_BUFFER_SIZE
67
68/* buffers */
69static char unzipbuf[UNZIP_BUFFER_SIZE];
70static char zipbuf[ZIP_BUFFER_SIZE];
71
72/*
73** zip_init
74** Initialize compression structures for a server.
75** If failed, zip_free() has to be called.
76*/
77int zip_init(aClient *cptr)
78{
79 cptr->zip = (aZdata *) MyMalloc(sizeof(aZdata));
80 cptr->zip->outcount = 0;
81
82 cptr->zip->in = (z_stream *) MyMalloc(sizeof(z_stream));
83 cptr->zip->in->avail_in = 0;
84 cptr->zip->in->total_in = 0;
85 cptr->zip->in->total_out = 0;
86 cptr->zip->in->zalloc = (alloc_func)0;
87 cptr->zip->in->zfree = (free_func)0;
88 cptr->zip->in->data_type = Z_ASCII;
89 if (inflateInit(cptr->zip->in) != Z_OK)
90 {
91 cptr->zip->out = NULL;
92 return -1;
93 }
94
95 cptr->zip->out = (z_stream *) MyMalloc(sizeof(z_stream));
96 cptr->zip->out->total_in = 0;
97 cptr->zip->out->total_out = 0;
98 cptr->zip->out->zalloc = (alloc_func)0;
99 cptr->zip->out->zfree = (free_func)0;
100 cptr->zip->out->data_type = Z_ASCII;
101 if (deflateInit(cptr->zip->out, ZIP_LEVEL) != Z_OK)
102 return -1;
103
104 return 0;
105}
106
107/*
108** zip_free
109*/
110void zip_free(aClient *cptr)
111{
112 cptr->flags &= ~FLAGS_ZIP;
113 if (cptr->zip)
114 {
115 if (cptr->zip->in)
116 inflateEnd(cptr->zip->in);
117 MyFree(cptr->zip->in);
118 if (cptr->zip->out)
119 deflateEnd(cptr->zip->out);
120 MyFree(cptr->zip->out);
121 MyFree(cptr->zip);
122 cptr->zip = NULL;
123 }
124}
125
126/*
127** unzip_packet
128** Unzip the content of the buffer, don't worry about any leftover.
129**
130** will return the uncompressed buffer, length will be updated.
131** if a fatal error occurs, length will be set to -1
132*/
133char *unzip_packet(aClient *cptr, char *buffer, int *length)
134{
135 Reg z_stream *zin = cptr->zip->in;
136 int r;
137
138 if (*length != 0 && zin->avail_in != 0)
139 {
140 sendto_flag(SCH_ERROR,
141 "assertion failed in unzip_packet(): %d %d",
142 *length, zin->avail_in);
143 sendto_flag(SCH_ERROR, "Please report to ircd-bugs@irc.org");
144 *length = -1;
145 return NULL;
146 }
147 if (*length)
148 {
149 zin->next_in = (Bytef *) buffer;
150 zin->avail_in = *length;
151 }
152 zin->next_out = (Bytef *) unzipbuf;
153 zin->avail_out = UNZIP_BUFFER_SIZE;
154 switch (r = inflate(zin, Z_SYNC_FLUSH))
155 {
156 case Z_OK:
157 cptr->flags &= ~FLAGS_ZIPRQ;
158 *length = UNZIP_BUFFER_SIZE - zin->avail_out;
159 return unzipbuf;
160
161 case Z_BUF_ERROR: /*no progress possible or output buffer too small*/
162 if (zin->avail_out == 0)
163 {
164 sendto_flag(SCH_ERROR,
165 "inflate() returned Z_BUF_ERROR: %s",
166 (zin->msg) ? zin->msg : "?");
167 *length = -1;
168 }
169 break;
170
171 case Z_DATA_ERROR: /* the buffer might not be compressed.. */
172 if ((cptr->flags & FLAGS_ZIPRQ) &&
173 !strncmp("ERROR ", buffer, 6))
174 {
175 cptr->flags &= ~(FLAGS_ZIP | FLAGS_ZIPRQ);
176 /*
177 * This is not sane at all. But if other server
178 * has sent an error now, it is probably closing
179 * the link as well.
180 */
181 return buffer;
182 }
183
184 /* no break */
185
186 default: /* error ! */
187 /* should probably mark link as dead or something... */
188 sendto_flag(SCH_ERROR, "inflate() error(%d): %s", r,
189 (zin->msg) ? zin->msg : "?");
190 *length = -1; /* report error condition */
191 break;
192 }
193 return NULL;
194}
195
196/*
197** zip_buffer
198** Zip the content of cptr->zip->outbuf and of the buffer,
199** put anything left in cptr->zip->outbuf, update cptr->zip->outcount
200**
201** if flush is set, then all available data will be compressed,
202** otherwise, compression only occurs if there's enough to compress,
203** or if we are reaching the maximum allowed size during a connect burst.
204**
205** will return the uncompressed buffer, length will be updated.
206** if a fatal error occurs, length will be set to -1
207*/
208char *zip_buffer(aClient *cptr, char *buffer, int *length, int flush)
209{
210 Reg z_stream *zout = cptr->zip->out;
211 int r;
212
213 if (buffer)
214 {
215 /* concatenate buffer in cptr->zip->outbuf */
216 bcopy(buffer, cptr->zip->outbuf + cptr->zip->outcount,*length);
217 cptr->zip->outcount += *length;
218 }
219 *length = 0;
220
221 if (!flush && ((cptr->zip->outcount < ZIP_MINIMUM) ||
222 ((cptr->zip->outcount < (ZIP_MAXIMUM - BUFSIZE)) &&
223 CBurst(cptr))))
224 return NULL;
225
226 zout->next_in = cptr->zip->outbuf;
227 zout->avail_in = cptr->zip->outcount;
228 zout->next_out = (Bytef *) zipbuf;
229 zout->avail_out = ZIP_BUFFER_SIZE;
230
231 switch (r = deflate(zout, Z_SYNC_FLUSH))
232 {
233 case Z_OK:
234 if (zout->avail_in)
235 {
236 /* can this occur?? I hope not... */
237 sendto_flag(SCH_ERROR,
238 "deflate() didn't process all available data!");
239 }
240 cptr->zip->outcount = 0;
241 *length = ZIP_BUFFER_SIZE - zout->avail_out;
242 return zipbuf;
243
244 default: /* error ! */
245 sendto_flag(SCH_ERROR, "deflate() error(%d): %s", r,
246 (zout->msg) ? zout->msg : "?");
247 *length = -1;
248 break;
249 }
250 return NULL;
251}
252
253#endif /* ZIP_LINKS */
254