rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: gt_utils.c,v 1.10 2004/04/17 06:05:54 hipnod Exp $
|
paulo@0
|
3 *
|
paulo@0
|
4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
|
paulo@0
|
5 *
|
paulo@0
|
6 * This program is free software; you can redistribute it and/or modify it
|
paulo@0
|
7 * under the terms of the GNU General Public License as published by the
|
paulo@0
|
8 * Free Software Foundation; either version 2, or (at your option) any
|
paulo@0
|
9 * later version.
|
paulo@0
|
10 *
|
paulo@0
|
11 * This program is distributed in the hope that it will be useful, but
|
paulo@0
|
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
|
paulo@0
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
paulo@0
|
14 * General Public License for more details.
|
paulo@0
|
15 */
|
paulo@0
|
16
|
paulo@0
|
17 #include "gt_gnutella.h"
|
paulo@0
|
18
|
paulo@0
|
19 #include "gt_utils.h"
|
paulo@0
|
20
|
paulo@0
|
21 #ifdef USE_ZLIB
|
paulo@0
|
22 #include <zlib.h>
|
paulo@0
|
23 #endif /* USE_ZLIB */
|
paulo@0
|
24
|
paulo@0
|
25 /*****************************************************************************/
|
paulo@0
|
26
|
paulo@0
|
27 int peer_addr (int fd, in_addr_t *r_ip, in_port_t *r_port)
|
paulo@0
|
28 {
|
paulo@0
|
29 struct sockaddr_in sin;
|
paulo@0
|
30 int len = sizeof (struct sockaddr_in);
|
paulo@0
|
31
|
paulo@0
|
32 if (getpeername (fd, (struct sockaddr *) &sin, &len) < 0)
|
paulo@0
|
33 return FALSE;
|
paulo@0
|
34
|
paulo@0
|
35 /* maybe port should be kept in network byte-order */
|
paulo@0
|
36 if (r_port)
|
paulo@0
|
37 *r_port = ntohs (sin.sin_port);
|
paulo@0
|
38
|
paulo@0
|
39 if (r_ip)
|
paulo@0
|
40 *r_ip = sin.sin_addr.s_addr;
|
paulo@0
|
41
|
paulo@0
|
42 return TRUE;
|
paulo@0
|
43 }
|
paulo@0
|
44
|
paulo@0
|
45 char *make_str (char *array, int len)
|
paulo@0
|
46 {
|
paulo@0
|
47 static int data_len = 0;
|
paulo@0
|
48 static char *data = 0;
|
paulo@0
|
49
|
paulo@0
|
50 if (len <= 0)
|
paulo@0
|
51 return "";
|
paulo@0
|
52
|
paulo@0
|
53 if (!data_len || data_len < len)
|
paulo@0
|
54 {
|
paulo@0
|
55 if (data)
|
paulo@0
|
56 free (data);
|
paulo@0
|
57
|
paulo@0
|
58 if (!(data = malloc (len + 1)))
|
paulo@0
|
59 return "(No memory for string)";
|
paulo@0
|
60 }
|
paulo@0
|
61
|
paulo@0
|
62 memcpy (data, array, len);
|
paulo@0
|
63
|
paulo@0
|
64 data[len] = 0;
|
paulo@0
|
65
|
paulo@0
|
66 if (len > data_len)
|
paulo@0
|
67 data_len = len;
|
paulo@0
|
68
|
paulo@0
|
69 return data;
|
paulo@0
|
70 }
|
paulo@0
|
71
|
paulo@0
|
72 void fprint_hex (FILE *f, char *buf, int len)
|
paulo@0
|
73 {
|
paulo@0
|
74 int i, j;
|
paulo@0
|
75 unsigned char *line;
|
paulo@0
|
76 unsigned char *end;
|
paulo@0
|
77
|
paulo@0
|
78 end = buf + len;
|
paulo@0
|
79
|
paulo@0
|
80 while ((line = buf) != end)
|
paulo@0
|
81 {
|
paulo@0
|
82 for (i = 0; i < 16; i++)
|
paulo@0
|
83 {
|
paulo@0
|
84 if (line + i == end)
|
paulo@0
|
85 break;
|
paulo@0
|
86
|
paulo@0
|
87 fprintf (f, "%02x ", line[i]);
|
paulo@0
|
88 }
|
paulo@0
|
89
|
paulo@0
|
90 for (j = i; j < 16; j++)
|
paulo@0
|
91 fprintf (f, " ");
|
paulo@0
|
92
|
paulo@0
|
93 fprintf (f, " ");
|
paulo@0
|
94
|
paulo@0
|
95 for (i = 0; i < 16; i++)
|
paulo@0
|
96 {
|
paulo@0
|
97 if (line + i == end)
|
paulo@0
|
98 break;
|
paulo@0
|
99
|
paulo@0
|
100 fprintf (f, "%c", isprint (line[i]) ? line[i] : '.');
|
paulo@0
|
101 }
|
paulo@0
|
102
|
paulo@0
|
103 buf += i;
|
paulo@0
|
104 fprintf (f, "\n");
|
paulo@0
|
105 }
|
paulo@0
|
106 }
|
paulo@0
|
107
|
paulo@0
|
108 /*****************************************************************************/
|
paulo@0
|
109 /* HTTP HEADER STORAGE */
|
paulo@0
|
110
|
paulo@0
|
111 #if 0
|
paulo@0
|
112 static unsigned long hash_lowercase (Dataset *d, void *key, size_t key_len)
|
paulo@0
|
113 {
|
paulo@0
|
114 char *str;
|
paulo@0
|
115 int i;
|
paulo@0
|
116 unsigned long hash;
|
paulo@0
|
117
|
paulo@0
|
118 for (hash = 0, i = 0; i < key_len; i++)
|
paulo@0
|
119 hash ^= tolower (str[i]);
|
paulo@0
|
120
|
paulo@0
|
121 return hash;
|
paulo@0
|
122 }
|
paulo@0
|
123
|
paulo@0
|
124 static int cmp_caseless (Dataset *d, DatasetNode *node, void *key,
|
paulo@0
|
125 size_t key_len)
|
paulo@0
|
126 {
|
paulo@0
|
127 return strncasecmp (node->key, key, MIN (node->key_len, key_len));
|
paulo@0
|
128 }
|
paulo@0
|
129
|
paulo@0
|
130 /* Like a Dataset, but stores case-insensitive strings for keys to
|
paulo@0
|
131 * string fields. */
|
paulo@0
|
132 Headers *headers_new ()
|
paulo@0
|
133 {
|
paulo@0
|
134 Dataset *dataset;
|
paulo@0
|
135
|
paulo@0
|
136 if (!(dataset = dataset_new (DATASET_DEFAULT)))
|
paulo@0
|
137 return NULL;
|
paulo@0
|
138
|
paulo@0
|
139 dataset->hash_func = hash_lowercase;
|
paulo@0
|
140
|
paulo@0
|
141 return hdrs;
|
paulo@0
|
142 }
|
paulo@0
|
143
|
paulo@0
|
144 char *header_lookup (Headers *hdrs, char *key)
|
paulo@0
|
145 {
|
paulo@0
|
146 char *value;
|
paulo@0
|
147
|
paulo@0
|
148 if (!hdrs || !key)
|
paulo@0
|
149 return NULL;
|
paulo@0
|
150
|
paulo@0
|
151 return dataset_lookupstr (dataset, key);
|
paulo@0
|
152 }
|
paulo@0
|
153
|
paulo@0
|
154 void header_insert (Headers **hdrs, char *key, char *value)
|
paulo@0
|
155 {
|
paulo@0
|
156 if (!d || !key)
|
paulo@0
|
157 return;
|
paulo@0
|
158
|
paulo@0
|
159 if (!(*hdrs) && !(*hdrs = headers_new ()))
|
paulo@0
|
160 return;
|
paulo@0
|
161
|
paulo@0
|
162 dataset_insertstr (hdrs->dataset, key, value);
|
paulo@0
|
163 }
|
paulo@0
|
164
|
paulo@0
|
165 void header_remove (Headers *hdrs, char *key)
|
paulo@0
|
166 {
|
paulo@0
|
167 if (!hdrs)
|
paulo@0
|
168 return NULL;
|
paulo@0
|
169
|
paulo@0
|
170 dataset_remove (hdrs->dataset, key, size);
|
paulo@0
|
171 }
|
paulo@0
|
172 #endif
|
paulo@0
|
173
|
paulo@0
|
174 /*****************************************************************************/
|
paulo@0
|
175 /* ZLIB WRAPPER ROUTINES */
|
paulo@0
|
176
|
paulo@0
|
177 static char *zlib_strerror (int error)
|
paulo@0
|
178 {
|
paulo@0
|
179 #ifndef USE_ZLIB
|
paulo@0
|
180 return NULL;
|
paulo@0
|
181 #else /* USE_ZLIB */
|
paulo@0
|
182 switch (error)
|
paulo@0
|
183 {
|
paulo@0
|
184 case Z_OK: return "OK";
|
paulo@0
|
185 case Z_STREAM_END: return "End of stream";
|
paulo@0
|
186 case Z_NEED_DICT: return "Decompressing dictionary needed";
|
paulo@0
|
187 case Z_STREAM_ERROR: return "Stream error";
|
paulo@0
|
188 case Z_ERRNO: return "Generic zlib error";
|
paulo@0
|
189 case Z_DATA_ERROR: return "Data error";
|
paulo@0
|
190 case Z_MEM_ERROR: return "Memory error";
|
paulo@0
|
191 case Z_BUF_ERROR: return "Buffer error";
|
paulo@0
|
192 case Z_VERSION_ERROR: return "Incompatible runtime zlib library";
|
paulo@0
|
193 default: break;
|
paulo@0
|
194 }
|
paulo@0
|
195
|
paulo@0
|
196 return "Invalid zlib error code";
|
paulo@0
|
197 #endif /* USE_ZLIB */
|
paulo@0
|
198 }
|
paulo@0
|
199
|
paulo@0
|
200 static void zstream_close (ZlibStream *stream)
|
paulo@0
|
201 {
|
paulo@0
|
202 #ifdef USE_ZLIB
|
paulo@0
|
203 switch (stream->type)
|
paulo@0
|
204 {
|
paulo@0
|
205 case ZSTREAM_INFLATE: inflateEnd (stream->streamptr); break;
|
paulo@0
|
206 case ZSTREAM_DEFLATE: deflateEnd (stream->streamptr); break;
|
paulo@0
|
207 default: break;
|
paulo@0
|
208 }
|
paulo@0
|
209
|
paulo@0
|
210 if (stream->streamptr)
|
paulo@0
|
211 free (stream->streamptr);
|
paulo@0
|
212
|
paulo@0
|
213 stream->type = ZSTREAM_NONE;
|
paulo@0
|
214 stream->streamptr = NULL;
|
paulo@0
|
215 #endif /* USE_ZLIB */
|
paulo@0
|
216 }
|
paulo@0
|
217
|
paulo@0
|
218 ZlibStream *zlib_stream_open (size_t max_size)
|
paulo@0
|
219 {
|
paulo@0
|
220 ZlibStream *stream;
|
paulo@0
|
221 char *data;
|
paulo@0
|
222
|
paulo@0
|
223 if (!(stream = malloc (sizeof (ZlibStream))))
|
paulo@0
|
224 return NULL;
|
paulo@0
|
225
|
paulo@0
|
226 if (!(data = malloc (max_size)))
|
paulo@0
|
227 {
|
paulo@0
|
228 free (stream);
|
paulo@0
|
229 return NULL;
|
paulo@0
|
230 }
|
paulo@0
|
231
|
paulo@0
|
232 memset (stream, 0, sizeof (ZlibStream));
|
paulo@0
|
233 memset (data, 0, max_size);
|
paulo@0
|
234
|
paulo@0
|
235 stream->start = data;
|
paulo@0
|
236 stream->end = data + max_size;
|
paulo@0
|
237 stream->data = data;
|
paulo@0
|
238 stream->pos = data;
|
paulo@0
|
239 stream->type = ZSTREAM_NONE;
|
paulo@0
|
240
|
paulo@0
|
241 return stream;
|
paulo@0
|
242 }
|
paulo@0
|
243
|
paulo@0
|
244 void zlib_stream_close (ZlibStream *stream)
|
paulo@0
|
245 {
|
paulo@0
|
246 if (!stream)
|
paulo@0
|
247 return;
|
paulo@0
|
248
|
paulo@0
|
249 if (stream->type != ZSTREAM_NONE)
|
paulo@0
|
250 zstream_close (stream);
|
paulo@0
|
251
|
paulo@0
|
252 if (stream->data)
|
paulo@0
|
253 free (stream->data);
|
paulo@0
|
254
|
paulo@0
|
255 free (stream);
|
paulo@0
|
256 }
|
paulo@0
|
257
|
paulo@0
|
258 int zlib_stream_write (ZlibStream *stream, char *data, size_t size)
|
paulo@0
|
259 {
|
paulo@0
|
260 if (!stream)
|
paulo@0
|
261 return 0;
|
paulo@0
|
262
|
paulo@0
|
263 /* check for overflow */
|
paulo@0
|
264 if (stream->pos + (size-1) > stream->end)
|
paulo@0
|
265 return 0;
|
paulo@0
|
266
|
paulo@0
|
267 memcpy (stream->pos, data, size);
|
paulo@0
|
268
|
paulo@0
|
269 stream->pos += size;
|
paulo@0
|
270
|
paulo@0
|
271 return size;
|
paulo@0
|
272 }
|
paulo@0
|
273
|
paulo@0
|
274 int zlib_stream_read (ZlibStream *stream, char **r_data)
|
paulo@0
|
275 {
|
paulo@0
|
276 size_t size;
|
paulo@0
|
277
|
paulo@0
|
278 if (stream->start == stream->pos)
|
paulo@0
|
279 return 0;
|
paulo@0
|
280
|
paulo@0
|
281 *r_data = stream->start;
|
paulo@0
|
282
|
paulo@0
|
283 size = stream->pos - stream->start;
|
paulo@0
|
284
|
paulo@0
|
285 stream->start = stream->pos;
|
paulo@0
|
286
|
paulo@0
|
287 return size;
|
paulo@0
|
288 }
|
paulo@0
|
289
|
paulo@0
|
290 int zlib_stream_inflate (ZlibStream *stream, char *zdata, size_t size)
|
paulo@0
|
291 {
|
paulo@0
|
292 #ifndef USE_ZLIB
|
paulo@0
|
293 return FALSE;
|
paulo@0
|
294 #else /* USE_ZLIB */
|
paulo@0
|
295 z_streamp inz;
|
paulo@0
|
296 int ret;
|
paulo@0
|
297 size_t free_size;
|
paulo@0
|
298
|
paulo@0
|
299 if (!stream)
|
paulo@0
|
300 return FALSE;
|
paulo@0
|
301
|
paulo@0
|
302 if (!stream->streamptr)
|
paulo@0
|
303 {
|
paulo@0
|
304 assert (stream->type == ZSTREAM_NONE);
|
paulo@0
|
305
|
paulo@0
|
306 if (!(inz = malloc (sizeof (*inz))))
|
paulo@0
|
307 return FALSE;
|
paulo@0
|
308
|
paulo@0
|
309 inz->zalloc = NULL;
|
paulo@0
|
310 inz->zfree = NULL;
|
paulo@0
|
311 inz->opaque = NULL;
|
paulo@0
|
312
|
paulo@0
|
313 if ((ret = inflateInit (inz)) != Z_OK)
|
paulo@0
|
314 {
|
paulo@0
|
315 GT->DBGFN (GT, "inflateInit error %s", zlib_strerror (ret));
|
paulo@0
|
316 free (inz);
|
paulo@0
|
317 return FALSE;
|
paulo@0
|
318 }
|
paulo@0
|
319
|
paulo@0
|
320 stream->type = ZSTREAM_INFLATE;
|
paulo@0
|
321 stream->streamptr = inz;
|
paulo@0
|
322 }
|
paulo@0
|
323
|
paulo@0
|
324 inz = stream->streamptr;
|
paulo@0
|
325
|
paulo@0
|
326 /* Argh, I think this is right, but I'm not sure about the +1 */
|
paulo@0
|
327 free_size = stream->end - stream->pos + 1;
|
paulo@0
|
328
|
paulo@0
|
329 inz->next_in = zdata;
|
paulo@0
|
330 inz->avail_in = size;
|
paulo@0
|
331 inz->next_out = stream->pos;
|
paulo@0
|
332 inz->avail_out = free_size;
|
paulo@0
|
333
|
paulo@0
|
334 GT->DBGFN (GT, "next_out: %p avail_out: %u", inz->next_out, inz->avail_out);
|
paulo@0
|
335
|
paulo@0
|
336 if ((ret = inflate (inz, Z_NO_FLUSH)) != Z_OK)
|
paulo@0
|
337 {
|
paulo@0
|
338 GT->DBGFN (GT, "decompression error: %s", zlib_strerror (ret));
|
paulo@0
|
339 return FALSE;
|
paulo@0
|
340 }
|
paulo@0
|
341
|
paulo@0
|
342 GT->DBGFN (GT, "inz->avail_in = %u, inz->avail_out = %u", inz->avail_in,
|
paulo@0
|
343 inz->avail_out);
|
paulo@0
|
344
|
paulo@0
|
345 stream->pos += free_size - inz->avail_out;
|
paulo@0
|
346
|
paulo@0
|
347 if (ret == Z_STREAM_END)
|
paulo@0
|
348 zstream_close (stream);
|
paulo@0
|
349
|
paulo@0
|
350 return TRUE;
|
paulo@0
|
351 #endif /* USE_ZLIB */
|
paulo@0
|
352 }
|