]>
Commit | Line | Data |
---|---|---|
f892c2bf | 1 | |
2 | /* | |
f0debecb | 3 | * $Id: access_log.cc,v 1.64 2001/01/02 00:09:55 wessels Exp $ |
f892c2bf | 4 | * |
5 | * DEBUG: section 46 Access Log | |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
e25c139f | 9 | * ---------------------------------------------------------- |
f892c2bf | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
efd900cb | 15 | * the Regents of the University of California. Please see the |
16 | * COPYRIGHT file for full details. Squid incorporates software | |
17 | * developed and/or copyrighted by other sources. Please see the | |
18 | * CREDITS file for full details. | |
f892c2bf | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
f892c2bf | 34 | */ |
35 | ||
36 | ||
37 | #include "squid.h" | |
38 | ||
5673c2e2 | 39 | static void accessLogSquid(AccessLogEntry * al); |
40 | static void accessLogCommon(AccessLogEntry * al); | |
41 | static Logfile *logfile = NULL; | |
c3609322 | 42 | #if HEADERS_LOG |
43 | static Logfile *headerslog = NULL; | |
44 | #endif | |
a7c05555 | 45 | |
e66d7923 | 46 | #if MULTICAST_MISS_STREAM |
47 | static int mcast_miss_fd = -1; | |
48 | static struct sockaddr_in mcast_miss_to; | |
49 | static void mcast_encode(unsigned int *, size_t, const unsigned int *); | |
50 | #endif | |
51 | ||
7a2f978b | 52 | const char *log_tags[] = |
53 | { | |
54 | "NONE", | |
55 | "TCP_HIT", | |
56 | "TCP_MISS", | |
57 | "TCP_REFRESH_HIT", | |
58 | "TCP_REF_FAIL_HIT", | |
59 | "TCP_REFRESH_MISS", | |
ee1679df | 60 | "TCP_CLIENT_REFRESH_MISS", |
7a2f978b | 61 | "TCP_IMS_HIT", |
7a2f978b | 62 | "TCP_SWAPFAIL_MISS", |
63 | "TCP_NEGATIVE_HIT", | |
64 | "TCP_MEM_HIT", | |
79a15e0a | 65 | "TCP_DENIED", |
b540e168 | 66 | "TCP_OFFLINE_HIT", |
efd900cb | 67 | #if LOG_TCP_REDIRECTS |
68 | "TCP_REDIRECT", | |
69 | #endif | |
7a2f978b | 70 | "UDP_HIT", |
7a2f978b | 71 | "UDP_MISS", |
72 | "UDP_DENIED", | |
73 | "UDP_INVALID", | |
74 | "UDP_MISS_NOFETCH", | |
071a3ae7 | 75 | "ICP_QUERY", |
7a2f978b | 76 | "LOG_TYPE_MAX" |
77 | }; | |
78 | ||
d21f1c54 | 79 | #if FORW_VIA_DB |
80 | typedef struct { | |
6c40d272 | 81 | hash_link hash; |
1afe05c5 | 82 | int n; |
d21f1c54 | 83 | } fvdb_entry; |
84 | static hash_table *via_table = NULL; | |
85 | static hash_table *forw_table = NULL; | |
86 | static void fvdbInit(void); | |
1afe05c5 | 87 | static void fvdbDumpTable(StoreEntry * e, hash_table * hash); |
88 | static void fvdbCount(hash_table * hash, const char *key); | |
d21f1c54 | 89 | static OBJH fvdbDumpVia; |
90 | static OBJH fvdbDumpForw; | |
91 | static FREE fvdbFreeEntry; | |
92 | static void fvdbClear(void); | |
93 | #endif | |
f892c2bf | 94 | |
95 | static int LogfileStatus = LOG_DISABLE; | |
f892c2bf | 96 | #define LOG_BUF_SZ (MAX_URL<<2) |
f892c2bf | 97 | |
98 | static const char c2x[] = | |
99 | "000102030405060708090a0b0c0d0e0f" | |
100 | "101112131415161718191a1b1c1d1e1f" | |
101 | "202122232425262728292a2b2c2d2e2f" | |
102 | "303132333435363738393a3b3c3d3e3f" | |
103 | "404142434445464748494a4b4c4d4e4f" | |
104 | "505152535455565758595a5b5c5d5e5f" | |
105 | "606162636465666768696a6b6c6d6e6f" | |
106 | "707172737475767778797a7b7c7d7e7f" | |
107 | "808182838485868788898a8b8c8d8e8f" | |
108 | "909192939495969798999a9b9c9d9e9f" | |
109 | "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" | |
110 | "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" | |
111 | "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" | |
112 | "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" | |
113 | "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" | |
114 | "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; | |
115 | ||
116 | /* log_quote -- URL-style encoding on MIME headers. */ | |
117 | ||
592da4ec | 118 | char * |
f892c2bf | 119 | log_quote(const char *header) |
120 | { | |
718644ff | 121 | int c; |
122 | int i; | |
123 | char *buf; | |
124 | char *buf_cursor; | |
f892c2bf | 125 | if (header == NULL) { |
126 | buf = xcalloc(1, 1); | |
127 | *buf = '\0'; | |
128 | return buf; | |
129 | } | |
130 | buf = xcalloc((strlen(header) * 3) + 1, 1); | |
131 | buf_cursor = buf; | |
132 | /* | |
133 | * We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF | |
134 | * which is the default escape list for the CPAN Perl5 URI module | |
135 | * modulo the inclusion of space (x40) to make the raw logs a bit | |
136 | * more readable. | |
137 | */ | |
79d39a72 | 138 | while ((c = *(const unsigned char *) header++) != '\0') { |
7e3ce7b9 | 139 | #if !OLD_LOG_MIME |
140 | if (c == '\r') { | |
141 | *buf_cursor++ = '\\'; | |
142 | *buf_cursor++ = 'r'; | |
143 | } else if (c == '\n') { | |
144 | *buf_cursor++ = '\\'; | |
145 | *buf_cursor++ = 'n'; | |
146 | } else | |
147 | #endif | |
148 | if (c <= 0x1F | |
149 | || c >= 0x7F | |
150 | #if OLD_LOG_MIME | |
151 | || c == '"' | |
152 | || c == '#' | |
153 | || c == '%' | |
154 | || c == ';' | |
155 | || c == '<' | |
156 | || c == '>' | |
157 | || c == '?' | |
158 | || c == '{' | |
159 | || c == '}' | |
160 | || c == '|' | |
161 | || c == '\\' | |
162 | || c == '^' | |
163 | || c == '~' | |
164 | || c == '`' | |
165 | #endif | |
166 | || c == '[' | |
f892c2bf | 167 | || c == ']') { |
168 | *buf_cursor++ = '%'; | |
169 | i = c * 2; | |
170 | *buf_cursor++ = c2x[i]; | |
171 | *buf_cursor++ = c2x[i + 1]; | |
7e3ce7b9 | 172 | #if !OLD_LOG_MIME |
173 | } else if (c == '\\') { | |
174 | *buf_cursor++ = '\\'; | |
175 | *buf_cursor++ = '\\'; | |
176 | #endif | |
f892c2bf | 177 | } else { |
79d39a72 | 178 | *buf_cursor++ = (char) c; |
f892c2bf | 179 | } |
180 | } | |
181 | *buf_cursor = '\0'; | |
182 | return buf; | |
183 | } | |
184 | ||
137ee196 | 185 | static void |
5673c2e2 | 186 | accessLogSquid(AccessLogEntry * al) |
f892c2bf | 187 | { |
e7b53d5d | 188 | const char *client = NULL; |
17a0a4ee | 189 | if (Config.onoff.log_fqdn) |
b22b7951 | 190 | client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); |
f892c2bf | 191 | if (client == NULL) |
192 | client = inet_ntoa(al->cache.caddr); | |
5673c2e2 | 193 | logfilePrintf(logfile, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s %s", |
f892c2bf | 194 | (int) current_time.tv_sec, |
195 | (int) current_time.tv_usec / 1000, | |
196 | al->cache.msec, | |
197 | client, | |
198 | log_tags[al->cache.code], | |
199 | al->http.code, | |
200 | al->cache.size, | |
201 | al->private.method_str, | |
202 | al->url, | |
203 | al->cache.ident, | |
b4e7f82d | 204 | al->hier.ping.timedout ? "TIMEOUT_" : "", |
f892c2bf | 205 | hier_strings[al->hier.code], |
206 | al->hier.host, | |
207 | al->http.content_type); | |
208 | } | |
209 | ||
137ee196 | 210 | static void |
5673c2e2 | 211 | accessLogCommon(AccessLogEntry * al) |
f892c2bf | 212 | { |
3a0bd885 | 213 | const char *client = NULL; |
17a0a4ee | 214 | if (Config.onoff.log_fqdn) |
f892c2bf | 215 | client = fqdncache_gethostbyaddr(al->cache.caddr, 0); |
216 | if (client == NULL) | |
217 | client = inet_ntoa(al->cache.caddr); | |
ccf44862 | 218 | logfilePrintf(logfile, "%s %s - [%s] \"%s %s HTTP/%d.%d\" %d %d %s:%s", |
f892c2bf | 219 | client, |
220 | al->cache.ident, | |
221 | mkhttpdlogtime(&squid_curtime), | |
222 | al->private.method_str, | |
223 | al->url, | |
ccf44862 | 224 | al->http.version.major, al->http.version.minor, |
f892c2bf | 225 | al->http.code, |
226 | al->cache.size, | |
227 | log_tags[al->cache.code], | |
228 | hier_strings[al->hier.code]); | |
229 | } | |
230 | ||
231 | void | |
232 | accessLogLog(AccessLogEntry * al) | |
233 | { | |
3a459d9d | 234 | LOCAL_ARRAY(char, ident_buf, USER_IDENT_SZ); |
137ee196 | 235 | |
f892c2bf | 236 | if (LogfileStatus != LOG_ENABLE) |
237 | return; | |
238 | if (al->url == NULL) | |
239 | al->url = dash_str; | |
240 | if (!al->http.content_type || *al->http.content_type == '\0') | |
241 | al->http.content_type = dash_str; | |
3a0bd885 | 242 | if (!al->cache.ident || *al->cache.ident == '\0') { |
3a459d9d | 243 | al->cache.ident = dash_str; |
244 | } else { | |
245 | xstrncpy(ident_buf, rfc1738_escape(al->cache.ident), USER_IDENT_SZ); | |
246 | al->cache.ident = ident_buf; | |
3a0bd885 | 247 | } |
f892c2bf | 248 | if (al->icp.opcode) |
27cd7235 | 249 | al->private.method_str = icp_opcode_str[al->icp.opcode]; |
f892c2bf | 250 | else |
251 | al->private.method_str = RequestMethodStr[al->http.method]; | |
4ea8f861 | 252 | if (al->hier.host[0] == '\0') |
253 | xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN); | |
137ee196 | 254 | |
17a0a4ee | 255 | if (Config.onoff.common_log) |
5673c2e2 | 256 | accessLogCommon(al); |
f892c2bf | 257 | else |
5673c2e2 | 258 | accessLogSquid(al); |
17a0a4ee | 259 | if (Config.onoff.log_mime_hdrs) { |
f892c2bf | 260 | char *ereq = log_quote(al->headers.request); |
261 | char *erep = log_quote(al->headers.reply); | |
5673c2e2 | 262 | logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); |
f892c2bf | 263 | safe_free(ereq); |
264 | safe_free(erep); | |
137ee196 | 265 | } else { |
5673c2e2 | 266 | logfilePrintf(logfile, "\n"); |
f892c2bf | 267 | } |
5673c2e2 | 268 | logfileFlush(logfile); |
e66d7923 | 269 | #if MULTICAST_MISS_STREAM |
270 | if (al->cache.code != LOG_TCP_MISS) | |
271 | (void) 0; | |
272 | else if (al->http.method != METHOD_GET) | |
273 | (void) 0; | |
274 | else if (mcast_miss_fd < 0) | |
275 | (void) 0; | |
276 | else { | |
277 | unsigned int ibuf[365]; | |
278 | size_t isize; | |
279 | xstrncpy((char *) ibuf, al->url, 364 * sizeof(int)); | |
280 | isize = ((strlen(al->url) + 8) / 8) * 2; | |
6355b0f5 | 281 | if (isize > 364) |
282 | isize = 364; | |
e66d7923 | 283 | mcast_encode((unsigned int *) ibuf, isize, |
0bdf2621 | 284 | (const unsigned int *) Config.mcast_miss.encode_key); |
e66d7923 | 285 | comm_udp_sendto(mcast_miss_fd, |
286 | &mcast_miss_to, sizeof(mcast_miss_to), | |
287 | ibuf, isize * sizeof(int)); | |
288 | } | |
289 | #endif | |
f892c2bf | 290 | } |
291 | ||
292 | void | |
293 | accessLogRotate(void) | |
294 | { | |
d21f1c54 | 295 | #if FORW_VIA_DB |
296 | fvdbClear(); | |
297 | #endif | |
5673c2e2 | 298 | if (NULL == logfile) |
f892c2bf | 299 | return; |
5673c2e2 | 300 | logfileRotate(logfile); |
c3609322 | 301 | #if HEADERS_LOG |
302 | logfileRotate(headerslog); | |
303 | #endif | |
f892c2bf | 304 | } |
305 | ||
306 | void | |
307 | accessLogClose(void) | |
308 | { | |
5673c2e2 | 309 | logfileClose(logfile); |
310 | logfile = NULL; | |
c3609322 | 311 | #if HEADERS_LOG |
312 | logfileClose(headerslog); | |
313 | headerslog = NULL; | |
314 | #endif | |
f892c2bf | 315 | } |
316 | ||
f892c2bf | 317 | void |
365e5b34 | 318 | hierarchyNote(HierarchyLogEntry * hl, |
f892c2bf | 319 | hier_code code, |
43c3424b | 320 | const char *cache_peer) |
f892c2bf | 321 | { |
322 | assert(hl != NULL); | |
323 | hl->code = code; | |
43c3424b | 324 | xstrncpy(hl->host, cache_peer, SQUIDHOSTNAMELEN); |
f892c2bf | 325 | } |
7a2f978b | 326 | |
327 | void | |
328 | accessLogInit(void) | |
329 | { | |
79d39a72 | 330 | assert(sizeof(log_tags) == (LOG_TYPE_MAX + 1) * sizeof(char *)); |
f0debecb | 331 | if (strcasecmp(Config.Log.access, "none") == 0) |
cce7e679 | 332 | return; |
08e8e020 | 333 | logfile = logfileOpen(Config.Log.access, MAX_URL << 1, 1); |
5673c2e2 | 334 | LogfileStatus = LOG_ENABLE; |
c3609322 | 335 | #if HEADERS_LOG |
336 | headerslog = logfileOpen("/usr/local/squid/logs/headers.log", 512); | |
337 | assert(NULL != headerslog); | |
338 | #endif | |
d21f1c54 | 339 | #if FORW_VIA_DB |
340 | fvdbInit(); | |
341 | #endif | |
e66d7923 | 342 | #if MULTICAST_MISS_STREAM |
343 | if (Config.mcast_miss.addr.s_addr != no_addr.s_addr) { | |
344 | memset(&mcast_miss_to, '\0', sizeof(mcast_miss_to)); | |
345 | mcast_miss_to.sin_family = AF_INET; | |
346 | mcast_miss_to.sin_port = htons(Config.mcast_miss.port); | |
347 | mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr; | |
348 | mcast_miss_fd = comm_open(SOCK_DGRAM, | |
349 | 0, | |
350 | Config.Addrs.udp_incoming, | |
351 | Config.mcast_miss.port, | |
352 | COMM_NONBLOCKING, | |
353 | "Multicast Miss Stream"); | |
354 | if (mcast_miss_fd < 0) | |
355 | fatal("Cannot open Multicast Miss Stream Socket"); | |
356 | debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n", | |
357 | mcast_miss_fd); | |
7e3ce7b9 | 358 | mcastSetTtl(mcast_miss_fd, Config.mcast_miss.ttl); |
e66d7923 | 359 | if (strlen(Config.mcast_miss.encode_key) < 16) |
360 | fatal("mcast_encode_key is too short, must be 16 characters"); | |
361 | } | |
362 | #endif | |
7a2f978b | 363 | } |
c6e7cab0 | 364 | |
365 | const char * | |
366 | accessLogTime(time_t t) | |
367 | { | |
368 | struct tm *tm; | |
369 | static char buf[128]; | |
370 | static time_t last_t = 0; | |
371 | if (t != last_t) { | |
372 | tm = localtime(&t); | |
373 | strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); | |
374 | last_t = t; | |
375 | } | |
376 | return buf; | |
377 | } | |
d21f1c54 | 378 | |
379 | ||
380 | #if FORW_VIA_DB | |
1afe05c5 | 381 | |
d21f1c54 | 382 | static void |
383 | fvdbInit(void) | |
384 | { | |
385 | via_table = hash_create((HASHCMP *) strcmp, 977, hash4); | |
386 | forw_table = hash_create((HASHCMP *) strcmp, 977, hash4); | |
749e40bf | 387 | cachemgrRegister("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1); |
d21f1c54 | 388 | cachemgrRegister("forw_headers", "X-Forwarded-For Request Headers", |
1da3b90b | 389 | fvdbDumpForw, 0, 1); |
d21f1c54 | 390 | } |
391 | ||
392 | static void | |
1afe05c5 | 393 | fvdbCount(hash_table * hash, const char *key) |
394 | { | |
395 | fvdb_entry *fv; | |
396 | if (NULL == hash) | |
397 | return; | |
398 | fv = hash_lookup(hash, key); | |
399 | if (NULL == fv) { | |
400 | fv = xcalloc(1, sizeof(fvdb_entry)); | |
186477c1 | 401 | fv->hash.key = xstrdup(key); |
402 | hash_join(hash, &fv->hash); | |
1afe05c5 | 403 | } |
404 | fv->n++; | |
d21f1c54 | 405 | } |
406 | ||
407 | void | |
408 | fvdbCountVia(const char *key) | |
409 | { | |
1afe05c5 | 410 | fvdbCount(via_table, key); |
d21f1c54 | 411 | } |
412 | ||
413 | void | |
414 | fvdbCountForw(const char *key) | |
415 | { | |
1afe05c5 | 416 | fvdbCount(forw_table, key); |
d21f1c54 | 417 | } |
418 | ||
1afe05c5 | 419 | static void |
420 | fvdbDumpTable(StoreEntry * e, hash_table * hash) | |
d21f1c54 | 421 | { |
1afe05c5 | 422 | hash_link *h; |
423 | fvdb_entry *fv; | |
424 | if (hash == NULL) | |
425 | return; | |
0f6bebac | 426 | hash_first(hash); |
b68ee087 | 427 | while ((h = hash_next(hash))) { |
1afe05c5 | 428 | fv = (fvdb_entry *) h; |
186477c1 | 429 | storeAppendPrintf(e, "%9d %s\n", fv->n, hashKeyStr(&fv->hash)); |
1afe05c5 | 430 | } |
d21f1c54 | 431 | } |
432 | ||
433 | static void | |
1afe05c5 | 434 | fvdbDumpVia(StoreEntry * e) |
d21f1c54 | 435 | { |
1afe05c5 | 436 | fvdbDumpTable(e, via_table); |
d21f1c54 | 437 | } |
1afe05c5 | 438 | |
d21f1c54 | 439 | static void |
1afe05c5 | 440 | fvdbDumpForw(StoreEntry * e) |
d21f1c54 | 441 | { |
1afe05c5 | 442 | fvdbDumpTable(e, forw_table); |
d21f1c54 | 443 | } |
444 | ||
445 | static | |
b644367b | 446 | void |
1afe05c5 | 447 | fvdbFreeEntry(void *data) |
d21f1c54 | 448 | { |
1afe05c5 | 449 | fvdb_entry *fv = data; |
186477c1 | 450 | xfree(fv->hash.key); |
1afe05c5 | 451 | xfree(fv); |
d21f1c54 | 452 | } |
453 | ||
454 | static void | |
455 | fvdbClear(void) | |
456 | { | |
457 | hashFreeItems(via_table, fvdbFreeEntry); | |
f6cb924d | 458 | hashFreeMemory(via_table); |
459 | via_table = hash_create((HASHCMP *) strcmp, 977, hash4); | |
d21f1c54 | 460 | hashFreeItems(forw_table, fvdbFreeEntry); |
f6cb924d | 461 | hashFreeMemory(forw_table); |
462 | forw_table = hash_create((HASHCMP *) strcmp, 977, hash4); | |
d21f1c54 | 463 | } |
464 | ||
1afe05c5 | 465 | #endif |
e66d7923 | 466 | |
467 | #if MULTICAST_MISS_STREAM | |
468 | /* | |
469 | * From http://www.io.com/~paulhart/game/algorithms/tea.html | |
470 | * | |
471 | * size of 'ibuf' must be a multiple of 2. | |
472 | * size of 'key' must be 4. | |
473 | * 'ibuf' is modified in place, encrypted data is written in | |
474 | * network byte order. | |
475 | */ | |
476 | static void | |
477 | mcast_encode(unsigned int *ibuf, size_t isize, const unsigned int *key) | |
478 | { | |
479 | unsigned int y; | |
480 | unsigned int z; | |
481 | unsigned int sum; | |
482 | const unsigned int delta = 0x9e3779b9; | |
483 | unsigned int n = 32; | |
484 | const unsigned int k0 = htonl(key[0]); | |
485 | const unsigned int k1 = htonl(key[1]); | |
486 | const unsigned int k2 = htonl(key[2]); | |
487 | const unsigned int k3 = htonl(key[3]); | |
488 | int i; | |
489 | for (i = 0; i < isize; i += 2) { | |
490 | y = htonl(ibuf[i]); | |
491 | z = htonl(ibuf[i + 1]); | |
492 | sum = 0; | |
493 | for (n = 32; n; n--) { | |
494 | sum += delta; | |
495 | y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1; | |
496 | z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3; | |
497 | } | |
498 | ibuf[i] = htonl(y); | |
499 | ibuf[i + 1] = htonl(z); | |
500 | } | |
501 | } | |
502 | ||
503 | #endif | |
c3609322 | 504 | |
505 | #if HEADERS_LOG | |
506 | void | |
507 | headersLog(int cs, int pq, method_t m, void *data) | |
508 | { | |
509 | HttpReply *rep; | |
510 | request_t *req; | |
511 | unsigned short magic = 0; | |
512 | unsigned char M = (unsigned char) m; | |
513 | unsigned short S; | |
514 | char *hmask; | |
515 | int ccmask = 0; | |
516 | if (0 == pq) { | |
517 | /* reply */ | |
518 | rep = data; | |
519 | req = NULL; | |
520 | magic = 0x0050; | |
521 | hmask = rep->header.mask; | |
522 | if (rep->cache_control) | |
523 | ccmask = rep->cache_control->mask; | |
524 | } else { | |
525 | /* request */ | |
526 | req = data; | |
527 | rep = NULL; | |
528 | magic = 0x0051; | |
529 | hmask = req->header.mask; | |
530 | if (req->cache_control) | |
531 | ccmask = req->cache_control->mask; | |
532 | } | |
533 | if (0 == cs) { | |
534 | /* client */ | |
535 | magic |= 0x4300; | |
536 | } else { | |
537 | /* server */ | |
538 | magic |= 0x5300; | |
539 | } | |
540 | magic = htons(magic); | |
541 | ccmask = htonl(ccmask); | |
542 | if (0 == pq) | |
543 | S = (unsigned short) rep->sline.status; | |
544 | else | |
545 | S = (unsigned short) HTTP_STATUS_NONE; | |
546 | logfileWrite(headerslog, &magic, sizeof(magic)); | |
547 | logfileWrite(headerslog, &M, sizeof(M)); | |
548 | logfileWrite(headerslog, &S, sizeof(S)); | |
549 | logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask)); | |
550 | logfileWrite(headerslog, &ccmask, sizeof(int)); | |
551 | logfileFlush(headerslog); | |
552 | } | |
553 | ||
554 | #endif |