]> git.ipfire.org Git - thirdparty/squid.git/blame - src/htcp.cc
Fix Cygwin build errors.
[thirdparty/squid.git] / src / htcp.cc
CommitLineData
d5d466fc 1
2/*
985c86bc 3 * $Id: htcp.cc,v 1.66 2006/05/08 23:38:33 robertc Exp $
9cef6668 4 *
5 * DEBUG: section 31 Hypertext Caching Protocol
6 * AUTHOR: Duane Wesssels
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9cef6668 9 * ----------------------------------------------------------
10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
9cef6668 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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
d5d466fc 34 */
35
c1b92ccb 36#include "squid.h"
924f73bc 37#include "htcp.h"
985c86bc 38#include "SquidTime.h"
e6ccf245 39#include "Store.h"
40#include "StoreClient.h"
528b2c61 41#include "HttpRequest.h"
402d6bec 42#include "comm.h"
0eb49b6d 43#include "MemBuf.h"
3b0d7130 44#include "http.h"
c1b92ccb 45
46typedef struct _Countstr Countstr;
62e76326 47
c1b92ccb 48typedef struct _htcpHeader htcpHeader;
62e76326 49
c1b92ccb 50typedef struct _htcpDataHeader htcpDataHeader;
62e76326 51
c1b92ccb 52typedef struct _htcpAuthHeader htcpAuthHeader;
62e76326 53
d5d466fc 54typedef struct _htcpStuff htcpStuff;
62e76326 55
a2edf5dc 56typedef struct _htcpDetail htcpDetail;
c1b92ccb 57
62e76326 58struct _Countstr
59{
a9245686 60 u_int16_t length;
59c4d35b 61 char *text;
c1b92ccb 62};
63
62e76326 64struct _htcpHeader
65{
a9245686 66 u_int16_t length;
59c4d35b 67 u_char major;
68 u_char minor;
c1b92ccb 69};
70
62e76326 71struct _htcpDataHeader
72{
a9245686 73 u_int16_t length;
eb9ae2f7 74#if !WORDS_BIGENDIAN
62e76326 75
76unsigned int opcode:
77 4;
78
79unsigned int response:
80 4;
eb9ae2f7 81#else
62e76326 82
83unsigned int response:
84 4;
85
86unsigned int opcode:
87 4;
eb9ae2f7 88#endif
89#if !WORDS_BIGENDIAN
62e76326 90
91unsigned int reserved:
92 6;
93
94unsigned int F1:
95 1;
96
97unsigned int RR:
98 1;
eb9ae2f7 99#else
62e76326 100
101unsigned int RR:
102 1;
103
104unsigned int F1:
105 1;
106
107unsigned int reserved:
108 6;
eb9ae2f7 109#endif
62e76326 110
a9245686 111 u_int32_t msg_id;
eb9ae2f7 112};
113
62e76326 114/* RR == 0 --> F1 = RESPONSE DESIRED FLAG */
115/* RR == 1 --> F1 = MESSAGE OVERALL FLAG */
116/* RR == 0 --> REQUEST */
117/* RR == 1 --> RESPONSE */
c1b92ccb 118
62e76326 119struct _htcpAuthHeader
120{
a9245686 121 u_int16_t length;
59c4d35b 122 time_t sig_time;
123 time_t sig_expire;
124 Countstr key_name;
125 Countstr signature;
c1b92ccb 126};
127
62e76326 128class htcpSpecifier : public StoreClient
129{
130
e6ccf245 131public:
b001e822 132 MEMPROXY_CLASS(htcpSpecifier);
e6ccf245 133
3b13a8fd 134 void created (StoreEntry *newEntry);
e6ccf245 135 void checkHit();
136 void checkedHit(StoreEntry *e);
62e76326 137
e6ccf245 138 void setFrom (struct sockaddr_in *from);
139 void setDataHeader (htcpDataHeader *);
eb9ae2f7 140 char *method;
141 char *uri;
142 char *version;
143 char *req_hdrs;
62e76326 144
e6ccf245 145private:
190154cf 146 HttpRequest *checkHitRequest;
62e76326 147
e6ccf245 148 struct sockaddr_in *from;
149 htcpDataHeader *dhdr;
eb9ae2f7 150};
151
b001e822 152MEMPROXY_CLASS_INLINE(htcpSpecifier)
153
62e76326 154struct _htcpDetail
155{
a2edf5dc 156 char *resp_hdrs;
157 char *entity_hdrs;
158 char *cache_hdrs;
159};
160
62e76326 161struct _htcpStuff
162{
d5d466fc 163 int op;
164 int rr;
165 int f1;
166 int response;
a9245686 167 u_int32_t msg_id;
a2edf5dc 168 htcpSpecifier S;
169 htcpDetail D;
c1b92ccb 170};
171
172enum {
59c4d35b 173 HTCP_NOP,
174 HTCP_TST,
175 HTCP_MON,
176 HTCP_SET,
eb9ae2f7 177 HTCP_CLR,
178 HTCP_END
179};
180
1afe05c5 181static const char *const htcpOpcodeStr[] =
62e76326 182 {
183 "HTCP_NOP",
184 "HTCP_TST",
185 "HTCP_MON",
186 "HTCP_SET",
187 "HTCP_CLR",
188 "HTCP_END"
189 };
c1b92ccb 190
191/*
192 * values for htcpDataHeader->response
193 */
194enum {
59c4d35b 195 AUTH_REQUIRED,
196 AUTH_FAILURE,
197 OPCODE_UNIMPLEMENTED,
198 MAJOR_VERSION_UNSUPPORTED,
199 MINOR_VERSION_UNSUPPORTED,
200 INVALID_OPCODE
c1b92ccb 201};
202
203/*
204 * values for htcpDataHeader->RR
205 */
206enum {
59c4d35b 207 RR_REQUEST,
208 RR_RESPONSE
c1b92ccb 209};
210
a9245686 211static u_int32_t msg_id_counter = 0;
d5d466fc 212static int htcpInSocket = -1;
213static int htcpOutSocket = -1;
26df9ec6 214#define N_QUERIED_KEYS 256
215static cache_key queried_keys[N_QUERIED_KEYS][MD5_DIGEST_CHARS];
b001e822 216static MemAllocator *htcpDetailPool = NULL;
675f3dff 217
59c4d35b 218
56714a1a 219static char *htcpBuildPacket(htcpStuff * stuff, ssize_t * len);
220static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz);
a2edf5dc 221static htcpDetail *htcpUnpackDetail(char *buf, int sz);
56714a1a 222static int htcpUnpackCountstr(char *buf, int sz, char **str);
223static ssize_t htcpBuildAuth(char *buf, size_t buflen);
224static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s);
225static ssize_t htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff);
226static ssize_t htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff);
227static ssize_t htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff);
228static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff);
229static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff);
230static void htcpFreeSpecifier(htcpSpecifier * s);
a2edf5dc 231static void htcpFreeDetail(htcpDetail * s);
62e76326 232
56714a1a 233static void htcpHandle(char *buf, int sz, struct sockaddr_in *from);
62e76326 234
56714a1a 235static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from);
62e76326 236
60fac9b5 237static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
62e76326 238
60fac9b5 239static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
62e76326 240
60fac9b5 241static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
62e76326 242
60fac9b5 243static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
56714a1a 244static void htcpRecv(int fd, void *data);
62e76326 245
56714a1a 246static void htcpSend(const char *buf, int len, struct sockaddr_in *to);
62e76326 247
26df9ec6 248static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *);
62e76326 249
26df9ec6 250static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
62e76326 251
60fac9b5 252static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *);
56714a1a 253
254static void
255htcpHexdump(const char *tag, const char *s, int sz)
256{
95eb77fe 257#if USE_HEXDUMP
60fac9b5 258 int i;
259 int k;
260 char hex[80];
d87ebd78 261 debug(31, 3) ("htcpHexdump %s\n", tag);
60fac9b5 262 memset(hex, '\0', 80);
62e76326 263
60fac9b5 264 for (i = 0; i < sz; i++) {
62e76326 265 k = i % 16;
266 snprintf(&hex[k * 3], 4, " %02x", (int) *(s + i));
267
268 if (k < 15 && i < (sz - 1))
269 continue;
270
271 debug(31, 3) ("\t%s\n", hex);
272
273 memset(hex, '\0', 80);
60fac9b5 274 }
62e76326 275
95eb77fe 276#endif
56714a1a 277}
d9f9d78b 278
eb9ae2f7 279/*
280 * STUFF FOR SENDING HTCP MESSAGES
281 */
282
56714a1a 283static ssize_t
d5d466fc 284htcpBuildAuth(char *buf, size_t buflen)
59c4d35b 285{
3340a3e6 286 htcpAuthHeader auth;
287 size_t copy_sz = 0;
a9245686 288 assert(2 == sizeof(u_int16_t));
3340a3e6 289 auth.length = htons(2);
290 copy_sz += 2;
291 assert(buflen >= copy_sz);
292 xmemcpy(buf, &auth, copy_sz);
293 return copy_sz;
294}
295
56714a1a 296static ssize_t
d5d466fc 297htcpBuildCountstr(char *buf, size_t buflen, const char *s)
298{
a9245686 299 u_int16_t length;
56714a1a 300 size_t len;
d5d466fc 301 off_t off = 0;
62e76326 302
d5d466fc 303 if (buflen - off < 2)
62e76326 304 return -1;
305
56714a1a 306 if (s)
62e76326 307 len = strlen(s);
56714a1a 308 else
62e76326 309 len = 0;
310
137a13ea 311 debugs(31, 3, "htcpBuildCountstr: LENGTH = " << len);
62e76326 312
d87ebd78 313 debug(31, 3) ("htcpBuildCountstr: TEXT = {%s}\n", s ? s : "<NULL>");
62e76326 314
a9245686 315 length = htons((u_int16_t) len);
62e76326 316
d5d466fc 317 xmemcpy(buf + off, &length, 2);
62e76326 318
d5d466fc 319 off += 2;
62e76326 320
d5d466fc 321 if (buflen - off < len)
62e76326 322 return -1;
323
56714a1a 324 if (len)
62e76326 325 xmemcpy(buf + off, s, len);
326
d5d466fc 327 off += len;
62e76326 328
d5d466fc 329 return off;
330}
331
56714a1a 332static ssize_t
d5d466fc 333htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff)
334{
335 ssize_t off = 0;
336 ssize_t s;
a2edf5dc 337 s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.method);
62e76326 338
d5d466fc 339 if (s < 0)
62e76326 340 return s;
341
d5d466fc 342 off += s;
62e76326 343
a2edf5dc 344 s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.uri);
62e76326 345
d5d466fc 346 if (s < 0)
62e76326 347 return s;
348
d5d466fc 349 off += s;
62e76326 350
a2edf5dc 351 s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.version);
62e76326 352
d5d466fc 353 if (s < 0)
62e76326 354 return s;
355
d5d466fc 356 off += s;
62e76326 357
a2edf5dc 358 s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.req_hdrs);
62e76326 359
d5d466fc 360 if (s < 0)
62e76326 361 return s;
362
d5d466fc 363 off += s;
62e76326 364
d87ebd78 365 debug(31, 3) ("htcpBuildSpecifier: size %d\n", (int) off);
62e76326 366
d5d466fc 367 return off;
368}
369
56714a1a 370static ssize_t
371htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff)
372{
373 ssize_t off = 0;
374 ssize_t s;
a2edf5dc 375 s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.resp_hdrs);
62e76326 376
56714a1a 377 if (s < 0)
62e76326 378 return s;
379
56714a1a 380 off += s;
62e76326 381
a2edf5dc 382 s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.entity_hdrs);
62e76326 383
56714a1a 384 if (s < 0)
62e76326 385 return s;
386
56714a1a 387 off += s;
62e76326 388
a2edf5dc 389 s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.cache_hdrs);
62e76326 390
56714a1a 391 if (s < 0)
62e76326 392 return s;
393
56714a1a 394 off += s;
62e76326 395
56714a1a 396 return off;
397}
398
399static ssize_t
d5d466fc 400htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff)
401{
0cdcddb9 402 switch (stuff->rr) {
62e76326 403
d9f9d78b 404 case RR_REQUEST:
62e76326 405 debug(31, 3) ("htcpBuildTstOpData: RR_REQUEST\n");
406 return htcpBuildSpecifier(buf, buflen, stuff);
407
d9f9d78b 408 case RR_RESPONSE:
62e76326 409 debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSE\n");
410 debug(31, 3) ("htcpBuildTstOpData: F1 = %d\n", stuff->f1);
411
412 if (stuff->f1) /* cache miss */
413 return 0;
414 else /* cache hit */
415 return htcpBuildDetail(buf, buflen, stuff);
416
d9f9d78b 417 default:
62e76326 418 fatal_dump("htcpBuildTstOpData: bad RR value");
0cdcddb9 419 }
62e76326 420
0cdcddb9 421 return 0;
d5d466fc 422}
423
56714a1a 424static ssize_t
d5d466fc 425htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff)
426{
427 ssize_t off = 0;
d87ebd78 428 debug(31, 3) ("htcpBuildOpData: opcode %s\n",
62e76326 429 htcpOpcodeStr[stuff->op]);
430
d5d466fc 431 switch (stuff->op) {
62e76326 432
d5d466fc 433 case HTCP_TST:
62e76326 434 off = htcpBuildTstOpData(buf + off, buflen, stuff);
435 break;
436
d5d466fc 437 default:
62e76326 438 assert(0);
439 break;
d5d466fc 440 }
62e76326 441
d5d466fc 442 return off;
443}
444
56714a1a 445static ssize_t
d5d466fc 446htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff)
447{
448 ssize_t off = 0;
449 ssize_t op_data_sz;
450 size_t hdr_sz = sizeof(htcpDataHeader);
451 htcpDataHeader hdr;
62e76326 452
d5d466fc 453 if (buflen < hdr_sz)
62e76326 454 return -1;
455
d5d466fc 456 off += hdr_sz; /* skip! */
62e76326 457
d5d466fc 458 op_data_sz = htcpBuildOpData(buf + off, buflen - off, stuff);
62e76326 459
d5d466fc 460 if (op_data_sz < 0)
62e76326 461 return op_data_sz;
462
d5d466fc 463 off += op_data_sz;
62e76326 464
d87ebd78 465 debug(31, 3) ("htcpBuildData: hdr.length = %d\n", (int) off);
62e76326 466
a9245686 467 hdr.length = (u_int16_t) off;
62e76326 468
d5d466fc 469 hdr.opcode = stuff->op;
62e76326 470
d5d466fc 471 hdr.response = stuff->response;
62e76326 472
d5d466fc 473 hdr.RR = stuff->rr;
62e76326 474
d5d466fc 475 hdr.F1 = stuff->f1;
62e76326 476
26df9ec6 477 hdr.msg_id = stuff->msg_id;
62e76326 478
d5d466fc 479 /* convert multi-byte fields */
480 hdr.length = htons(hdr.length);
62e76326 481
eb9ae2f7 482 hdr.msg_id = htonl(hdr.msg_id);
62e76326 483
d5d466fc 484 xmemcpy(buf, &hdr, hdr_sz);
62e76326 485
d87ebd78 486 debug(31, 3) ("htcpBuildData: size %d\n", (int) off);
62e76326 487
d5d466fc 488 return off;
489}
490
56714a1a 491static char *
d5d466fc 492htcpBuildPacket(htcpStuff * stuff, ssize_t * len)
3340a3e6 493{
d5d466fc 494 size_t buflen = 8192;
495 size_t s;
496 ssize_t off = 0;
497 size_t hdr_sz = sizeof(htcpHeader);
498 htcpHeader hdr;
e6ccf245 499 char *buf = (char *)xcalloc(buflen, 1);
d5d466fc 500 /* skip the header -- we don't know the overall length */
62e76326 501
9bc73deb 502 if (buflen < hdr_sz) {
62e76326 503 xfree(buf);
504 return NULL;
9bc73deb 505 }
62e76326 506
d5d466fc 507 off += hdr_sz;
508 s = htcpBuildData(buf + off, buflen - off, stuff);
62e76326 509
9bc73deb 510 if (s < 0) {
62e76326 511 xfree(buf);
512 return NULL;
9bc73deb 513 }
62e76326 514
d5d466fc 515 off += s;
516 s = htcpBuildAuth(buf + off, buflen - off);
62e76326 517
9bc73deb 518 if (s < 0) {
62e76326 519 xfree(buf);
520 return NULL;
9bc73deb 521 }
62e76326 522
d5d466fc 523 off += s;
a9245686 524 hdr.length = htons((u_int16_t) off);
d5d466fc 525 hdr.major = 0;
526 hdr.minor = 0;
527 xmemcpy(buf, &hdr, hdr_sz);
528 *len = off;
d87ebd78 529 debug(31, 3) ("htcpBuildPacket: size %d\n", (int) off);
d5d466fc 530 return buf;
3340a3e6 531}
532
56714a1a 533static void
62e76326 534
56714a1a 535htcpSend(const char *buf, int len, struct sockaddr_in *to)
3340a3e6 536{
d5d466fc 537 int x;
d87ebd78 538 debug(31, 3) ("htcpSend: %s/%d\n",
62e76326 539 inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port));
56714a1a 540 htcpHexdump("htcpSend", buf, len);
d5d466fc 541 x = comm_udp_sendto(htcpOutSocket,
62e76326 542 to,
543
544 sizeof(struct sockaddr_in),
545 buf,
546 len);
547
d5d466fc 548 if (x < 0)
62e76326 549 debug(31, 0) ("htcpSend: FD %d sendto: %s\n", htcpOutSocket, xstrerror());
c4ebc830 550 else
551 statCounter.htcp.pkts_sent++;
3340a3e6 552}
553
eb9ae2f7 554/*
555 * STUFF FOR RECEIVING HTCP MESSAGES
556 */
557
e6ccf245 558void
62e76326 559
e6ccf245 560htcpSpecifier::setFrom (struct sockaddr_in *aSocket)
561{
562 from = aSocket;
563}
564
565void
566htcpSpecifier::setDataHeader (htcpDataHeader *aDataHeader)
567{
568 dhdr = aDataHeader;
569}
570
eb9ae2f7 571static void
572htcpFreeSpecifier(htcpSpecifier * s)
573{
3a3c723d 574 safe_free(s->method);
575 safe_free(s->uri);
576 safe_free(s->version);
577 safe_free(s->req_hdrs);
e6ccf245 578 delete s;
eb9ae2f7 579}
580
a2edf5dc 581static void
582htcpFreeDetail(htcpDetail * d)
583{
3a3c723d 584 safe_free(d->resp_hdrs);
585 safe_free(d->entity_hdrs);
586 safe_free(d->cache_hdrs);
b001e822 587 htcpDetailPool->free(d);
a2edf5dc 588}
589
56714a1a 590static int
eb9ae2f7 591htcpUnpackCountstr(char *buf, int sz, char **str)
592{
a9245686 593 u_int16_t l;
d87ebd78 594 debug(31, 3) ("htcpUnpackCountstr: sz = %d\n", sz);
62e76326 595
1afe05c5 596 if (sz < 2) {
62e76326 597 debug(31, 3) ("htcpUnpackCountstr: sz < 2\n");
598 return -1;
1afe05c5 599 }
62e76326 600
56714a1a 601 htcpHexdump("htcpUnpackCountstr", buf, sz);
1afe05c5 602 xmemcpy(&l, buf, 2);
56714a1a 603 l = ntohs(l);
1afe05c5 604 buf += 2;
605 sz -= 2;
d87ebd78 606 debug(31, 3) ("htcpUnpackCountstr: LENGTH = %d\n", (int) l);
62e76326 607
1afe05c5 608 if (sz < l) {
62e76326 609 debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz, l);
610 return -1;
1afe05c5 611 }
62e76326 612
1afe05c5 613 if (str) {
62e76326 614 *str = (char *)xmalloc(l + 1);
615 xstrncpy(*str, buf, l + 1);
616 debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str);
1afe05c5 617 }
62e76326 618
1afe05c5 619 return (int) l + 2;
eb9ae2f7 620}
621
56714a1a 622static htcpSpecifier *
eb9ae2f7 623htcpUnpackSpecifier(char *buf, int sz)
624{
e6ccf245 625 htcpSpecifier *s = new htcpSpecifier;
1afe05c5 626 int o;
d87ebd78 627 debug(31, 3) ("htcpUnpackSpecifier: %d bytes\n", (int) sz);
1afe05c5 628 o = htcpUnpackCountstr(buf, sz, &s->method);
62e76326 629
1afe05c5 630 if (o < 0) {
62e76326 631 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
632 htcpFreeSpecifier(s);
633 return NULL;
1afe05c5 634 }
62e76326 635
1afe05c5 636 buf += o;
637 sz -= o;
1afe05c5 638 o = htcpUnpackCountstr(buf, sz, &s->uri);
62e76326 639
1afe05c5 640 if (o < 0) {
62e76326 641 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n");
642 htcpFreeSpecifier(s);
643 return NULL;
1afe05c5 644 }
62e76326 645
1afe05c5 646 buf += o;
647 sz -= o;
1afe05c5 648 o = htcpUnpackCountstr(buf, sz, &s->version);
62e76326 649
1afe05c5 650 if (o < 0) {
62e76326 651 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n");
652 htcpFreeSpecifier(s);
653 return NULL;
1afe05c5 654 }
62e76326 655
1afe05c5 656 buf += o;
657 sz -= o;
1afe05c5 658 o = htcpUnpackCountstr(buf, sz, &s->req_hdrs);
62e76326 659
1afe05c5 660 if (o < 0) {
62e76326 661 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n");
662 htcpFreeSpecifier(s);
663 return NULL;
1afe05c5 664 }
62e76326 665
1afe05c5 666 buf += o;
667 sz -= o;
d87ebd78 668 debug(31, 3) ("htcpUnpackSpecifier: %d bytes left\n", sz);
1afe05c5 669 return s;
eb9ae2f7 670}
671
a2edf5dc 672static htcpDetail *
673htcpUnpackDetail(char *buf, int sz)
674{
b001e822 675 htcpDetail *d = static_cast<htcpDetail *>(htcpDetailPool->alloc());
a2edf5dc 676 int o;
d87ebd78 677 debug(31, 3) ("htcpUnpackDetail: %d bytes\n", (int) sz);
a2edf5dc 678 o = htcpUnpackCountstr(buf, sz, &d->resp_hdrs);
62e76326 679
a2edf5dc 680 if (o < 0) {
62e76326 681 debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n");
682 htcpFreeDetail(d);
683 return NULL;
a2edf5dc 684 }
62e76326 685
a2edf5dc 686 buf += o;
687 sz -= o;
688 o = htcpUnpackCountstr(buf, sz, &d->entity_hdrs);
62e76326 689
a2edf5dc 690 if (o < 0) {
62e76326 691 debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n");
692 htcpFreeDetail(d);
693 return NULL;
a2edf5dc 694 }
62e76326 695
a2edf5dc 696 buf += o;
697 sz -= o;
698 o = htcpUnpackCountstr(buf, sz, &d->cache_hdrs);
62e76326 699
a2edf5dc 700 if (o < 0) {
62e76326 701 debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n");
702 htcpFreeDetail(d);
703 return NULL;
a2edf5dc 704 }
62e76326 705
a2edf5dc 706 buf += o;
707 sz -= o;
d87ebd78 708 debug(31, 3) ("htcpUnpackDetail: %d bytes left\n", sz);
a2edf5dc 709 return d;
710}
711
eb9ae2f7 712static void
62e76326 713
886f2785 714htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from)
60fac9b5 715{
716 htcpStuff stuff;
717 char *pkt;
75faaa7a 718 HttpHeader hdr(hoHtcpReply);
2dcc81d4 719 MemBuf mb;
720 Packer p;
60fac9b5 721 ssize_t pktlen;
2dcc81d4 722 char *host;
723 int rtt = 0;
724 int hops = 0;
725 int samp = 0;
726 char cto_buf[128];
9bc73deb 727 memset(&stuff, '\0', sizeof(stuff));
60fac9b5 728 stuff.op = HTCP_TST;
729 stuff.rr = RR_RESPONSE;
44e237d0 730 stuff.f1 = 0;
731 stuff.response = e ? 0 : 1;
7e3ce7b9 732 debug(31, 3) ("htcpTstReply: response = %d\n", stuff.response);
26df9ec6 733 stuff.msg_id = dhdr->msg_id;
62e76326 734
735 if (spec)
736 {
2fe7eff9 737 mb.init();
62e76326 738 packerToMemInit(&p, &mb);
62e76326 739 stuff.S.method = spec->method;
740 stuff.S.uri = spec->uri;
741 stuff.S.version = spec->version;
742 stuff.S.req_hdrs = spec->req_hdrs;
61f4f11b 743 hdr.putInt(HDR_AGE,
744 e->timestamp <= squid_curtime ?
745 squid_curtime - e->timestamp : 0);
746 hdr.packInto(&p);
62e76326 747 stuff.D.resp_hdrs = xstrdup(mb.buf);
748 debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}\n", stuff.D.resp_hdrs);
2fe7eff9 749 mb.reset();
61f4f11b 750 hdr.reset();
62e76326 751
752 if (e->expires > -1)
61f4f11b 753 hdr.putTime(HDR_EXPIRES, e->expires);
62e76326 754
755 if (e->lastmod > -1)
61f4f11b 756 hdr.putTime(HDR_LAST_MODIFIED, e->lastmod);
62e76326 757
61f4f11b 758 hdr.packInto(&p);
62e76326 759
760 stuff.D.entity_hdrs = xstrdup(mb.buf);
761
762 debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}\n", stuff.D.entity_hdrs);
763
2fe7eff9 764 mb.reset();
62e76326 765
61f4f11b 766 hdr.reset();
62e76326 767
768 if ((host = urlHostname(spec->uri))) {
769 netdbHostData(host, &samp, &rtt, &hops);
770
771 if (rtt || hops) {
772 snprintf(cto_buf, 128, "%s %d %f %d",
773 host, samp, 0.001 * rtt, hops);
61f4f11b 774 hdr.putExt("Cache-to-Origin", cto_buf);
62e76326 775 }
776 }
777
61f4f11b 778 hdr.packInto(&p);
62e76326 779 stuff.D.cache_hdrs = xstrdup(mb.buf);
780 debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}\n", stuff.D.cache_hdrs);
2fe7eff9 781 mb.clean();
519e0948 782 hdr.clean();
62e76326 783 packerClean(&p);
60fac9b5 784 }
62e76326 785
60fac9b5 786 pkt = htcpBuildPacket(&stuff, &pktlen);
62e76326 787
788 if (pkt == NULL)
789 {
790 debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n");
791 return;
60fac9b5 792 }
62e76326 793
60fac9b5 794 htcpSend(pkt, (int) pktlen, from);
3a3c723d 795 xfree(pkt);
60fac9b5 796}
797
798static void
62e76326 799
60fac9b5 800htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
eb9ae2f7 801{
d87ebd78 802 debug(31, 3) ("htcpHandleNop: Unimplemented\n");
eb9ae2f7 803}
804
e6ccf245 805void
806htcpSpecifier::checkHit()
32b3cf93 807{
985c86bc 808 method_t m = HttpRequestMethod(method);
7e3ce7b9 809 char *blk_end;
c21ad0f5 810 checkHitRequest = HttpRequest::CreateFromUrlAndMethod(uri, m);
62e76326 811
e6ccf245 812 if (NULL == checkHitRequest) {
62e76326 813 debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
814 checkedHit(NullStoreEntry::getInstance());
815 return;
7e3ce7b9 816 }
62e76326 817
e6ccf245 818 blk_end = req_hdrs + strlen(req_hdrs);
62e76326 819
61f4f11b 820 if (!checkHitRequest->header.parse(req_hdrs, blk_end)) {
62e76326 821 debug(31, 3) ("htcpCheckHit: NO; failed to parse request headers\n");
5cafad19 822 delete checkHitRequest;
62e76326 823 checkHitRequest = NULL;
824 checkedHit(NullStoreEntry::getInstance());
825 return;
f66a9ef4 826 }
62e76326 827
3b13a8fd 828 StoreEntry::getPublicByRequest(this, checkHitRequest);
e6ccf245 829}
830
831void
3b13a8fd 832htcpSpecifier::created (StoreEntry *e)
e6ccf245 833{
834 StoreEntry *hit=NULL;
835 assert (e);
62e76326 836
e6ccf245 837 if (e->isNull()) {
62e76326 838 debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
839 goto miss;
f66a9ef4 840 }
62e76326 841
f66a9ef4 842 if (!storeEntryValidToSend(e)) {
62e76326 843 debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
844 goto miss;
f66a9ef4 845 }
62e76326 846
e6ccf245 847 if (refreshCheckHTCP(e, checkHitRequest)) {
62e76326 848 debug(31, 3) ("htcpCheckHit: NO; cached response is stale\n");
849 goto miss;
7e3ce7b9 850 }
62e76326 851
f66a9ef4 852 debug(31, 3) ("htcpCheckHit: YES!?\n");
853 hit = e;
62e76326 854
855miss:
5cafad19 856 delete checkHitRequest;
e6ccf245 857 checkedHit (hit);
32b3cf93 858}
859
eb9ae2f7 860static void
62e76326 861
60fac9b5 862htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
eb9ae2f7 863{
d87ebd78 864 debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz);
62e76326 865
60fac9b5 866 if (hdr->RR == RR_REQUEST)
62e76326 867 htcpHandleTstRequest(hdr, buf, sz, from);
60fac9b5 868 else
62e76326 869 htcpHandleTstResponse(hdr, buf, sz, from);
60fac9b5 870}
871
75faaa7a 872HtcpReplyData::HtcpReplyData() : hdr(hoHtcpReply)
873{}
874
60fac9b5 875static void
62e76326 876
60fac9b5 877htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
878{
a2edf5dc 879 htcpReplyData htcpReply;
880 cache_key *key = NULL;
26df9ec6 881 htcpDetail *d = NULL;
a2edf5dc 882 char *t;
62e76326 883
884 if (hdr->F1 == 1)
885 {
886 debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
887 return;
44e237d0 888 }
62e76326 889
26df9ec6 890 htcpReply.msg_id = hdr->msg_id;
d87ebd78 891 debug(31, 3) ("htcpHandleTstResponse: msg_id = %d\n", (int) htcpReply.msg_id);
44e237d0 892 htcpReply.hit = hdr->response ? 0 : 1;
62e76326 893
894 if (hdr->F1)
895 {
896 debug(31, 3) ("htcpHandleTstResponse: MISS\n");
897 } else
898 {
899 debug(31, 3) ("htcpHandleTstResponse: HIT\n");
900 d = htcpUnpackDetail(buf, sz);
901
902 if (d == NULL) {
903 debug(31, 1) ("htcpHandleTstResponse: bad DETAIL\n");
904 return;
905 }
906
907 if ((t = d->resp_hdrs))
61f4f11b 908 htcpReply.hdr.parse(t, t + strlen(t));
62e76326 909
910 if ((t = d->entity_hdrs))
61f4f11b 911 htcpReply.hdr.parse(t, t + strlen(t));
62e76326 912
913 if ((t = d->cache_hdrs))
61f4f11b 914 htcpReply.hdr.parse(t, t + strlen(t));
a2edf5dc 915 }
62e76326 916
26df9ec6 917 key = queried_keys[htcpReply.msg_id % N_QUERIED_KEYS];
d87ebd78 918 debug(31, 3) ("htcpHandleTstResponse: key (%p) %s\n", key, storeKeyText(key));
a2edf5dc 919 neighborsHtcpReply(key, &htcpReply, from);
519e0948 920 htcpReply.hdr.clean();
62e76326 921
26df9ec6 922 if (d)
62e76326 923 htcpFreeDetail(d);
60fac9b5 924}
925
926static void
62e76326 927
886f2785 928htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from)
60fac9b5 929{
930 /* buf should be a SPECIFIER */
931 htcpSpecifier *s;
62e76326 932
933 if (sz == 0)
934 {
935 debug(31, 3) ("htcpHandleTst: nothing to do\n");
936 return;
60fac9b5 937 }
62e76326 938
44e237d0 939 if (dhdr->F1 == 0)
62e76326 940 return;
941
e6ccf245 942 /* s is a new object */
60fac9b5 943 s = htcpUnpackSpecifier(buf, sz);
62e76326 944
e6ccf245 945 s->setFrom (from);
62e76326 946
e6ccf245 947 s->setDataHeader (dhdr);
62e76326 948
949 if (NULL == s)
950 {
951 debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
952 return;
1afe05c5 953 }
62e76326 954
d87ebd78 955 debug(31, 3) ("htcpHandleTstRequest: %s %s %s\n",
62e76326 956 s->method,
957 s->uri,
958 s->version);
d87ebd78 959 debug(31, 3) ("htcpHandleTstRequest: %s\n", s->req_hdrs);
e6ccf245 960 s->checkHit();
961}
962
963void
964htcpSpecifier::checkedHit(StoreEntry *e)
965{
966 if (e)
62e76326 967 htcpTstReply(dhdr, e, this, from); /* hit */
32b3cf93 968 else
62e76326 969 htcpTstReply(dhdr, NULL, NULL, from); /* cache miss */
970
e6ccf245 971 htcpFreeSpecifier(this);
d9f9d78b 972}
973
974static void
62e76326 975
60fac9b5 976htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
eb9ae2f7 977{
d87ebd78 978 debug(31, 3) ("htcpHandleMon: Unimplemented\n");
eb9ae2f7 979}
980
981static void
62e76326 982
60fac9b5 983htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
eb9ae2f7 984{
d87ebd78 985 debug(31, 3) ("htcpHandleSet: Unimplemented\n");
eb9ae2f7 986}
987
988static void
62e76326 989
56714a1a 990htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
eb9ae2f7 991{
992 htcpDataHeader hdr;
e6ccf245 993 assert (sz >= 0);
62e76326 994
995 if ((size_t)sz < sizeof(htcpDataHeader))
996 {
997 debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader size\n");
998 return;
eb9ae2f7 999 }
62e76326 1000
eb9ae2f7 1001 xmemcpy(&hdr, buf, sizeof(htcpDataHeader));
1002 hdr.length = ntohs(hdr.length);
26df9ec6 1003 hdr.msg_id = ntohl(hdr.msg_id);
d87ebd78 1004 debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
1005 debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr.length);
62e76326 1006
1007 if (hdr.opcode >= HTCP_END)
1008 {
1009 debug(31, 0) ("htcpHandleData: client %s, opcode %d out of range\n",
1010 inet_ntoa(from->sin_addr),
1011 (int) hdr.opcode);
1012 return;
eb9ae2f7 1013 }
62e76326 1014
d87ebd78 1015 debug(31, 3) ("htcpHandleData: opcode = %d %s\n",
62e76326 1016 (int) hdr.opcode, htcpOpcodeStr[hdr.opcode]);
d87ebd78 1017 debug(31, 3) ("htcpHandleData: response = %d\n", (int) hdr.response);
1018 debug(31, 3) ("htcpHandleData: F1 = %d\n", (int) hdr.F1);
1019 debug(31, 3) ("htcpHandleData: RR = %d\n", (int) hdr.RR);
1020 debug(31, 3) ("htcpHandleData: msg_id = %d\n", (int) hdr.msg_id);
62e76326 1021
1022 if (sz < hdr.length)
1023 {
1024 debug(31, 0) ("htcpHandle: sz < hdr.length\n");
1025 return;
eb9ae2f7 1026 }
62e76326 1027
60fac9b5 1028 /*
1029 * set sz = hdr.length so we ignore any AUTH fields following
1030 * the DATA.
1031 */
1032 sz = (int) hdr.length;
62e76326 1033
eb9ae2f7 1034 buf += sizeof(htcpDataHeader);
62e76326 1035
eb9ae2f7 1036 sz -= sizeof(htcpDataHeader);
62e76326 1037
d87ebd78 1038 debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
62e76326 1039
56714a1a 1040 htcpHexdump("htcpHandleData", buf, sz);
62e76326 1041
1042 switch (hdr.opcode)
1043 {
1044
eb9ae2f7 1045 case HTCP_NOP:
62e76326 1046 htcpHandleNop(&hdr, buf, sz, from);
1047 break;
1048
eb9ae2f7 1049 case HTCP_TST:
62e76326 1050 htcpHandleTst(&hdr, buf, sz, from);
1051 break;
1052
eb9ae2f7 1053 case HTCP_MON:
62e76326 1054 htcpHandleMon(&hdr, buf, sz, from);
1055 break;
1056
eb9ae2f7 1057 case HTCP_SET:
62e76326 1058 htcpHandleSet(&hdr, buf, sz, from);
1059 break;
1060
2caa57ef 1061 case HTCP_CLR:
62e76326 1062 debug(31, 1) ("htcpHandleData: client %s, CLR not supported\n",
1063 inet_ntoa(from->sin_addr));
1064 break;
1065
eb9ae2f7 1066 default:
62e76326 1067 assert(0);
1068 break;
eb9ae2f7 1069 }
1070}
1071
1072static void
62e76326 1073
eb9ae2f7 1074htcpHandle(char *buf, int sz, struct sockaddr_in *from)
1075{
1076 htcpHeader htcpHdr;
e6ccf245 1077 assert (sz >= 0);
62e76326 1078
1079 if ((size_t)sz < sizeof(htcpHeader))
1080 {
1081 debug(31, 0) ("htcpHandle: msg size less than htcpHeader size\n");
1082 return;
eb9ae2f7 1083 }
62e76326 1084
56714a1a 1085 htcpHexdump("htcpHandle", buf, sz);
eb9ae2f7 1086 xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
1087 htcpHdr.length = ntohs(htcpHdr.length);
d87ebd78 1088 debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr.length);
1089 debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr.major);
1090 debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr.minor);
62e76326 1091
1092 if (sz != htcpHdr.length)
1093 {
1094 debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n",
1095 sz, htcpHdr.length,
1096 inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
1097 return;
eb9ae2f7 1098 }
62e76326 1099
eb9ae2f7 1100 buf += sizeof(htcpHeader);
1101 sz -= sizeof(htcpHeader);
56714a1a 1102 htcpHandleData(buf, sz, from);
eb9ae2f7 1103}
1104
56714a1a 1105static void
eb9ae2f7 1106htcpRecv(int fd, void *data)
1107{
1108 static char buf[8192];
1109 int len;
62e76326 1110
eb9ae2f7 1111 static struct sockaddr_in from;
62e76326 1112
e6ccf245 1113 socklen_t flen = sizeof(struct sockaddr_in);
eb9ae2f7 1114 memset(&from, '\0', flen);
62e76326 1115
7d21986b 1116 len = comm_udp_recvfrom(fd, buf, 8192, 0, (struct sockaddr *) &from, &flen);
d87ebd78 1117 debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n",
62e76326 1118 fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
c4ebc830 1119
1120 if (len)
1121 statCounter.htcp.pkts_recv++;
1122
eb9ae2f7 1123 htcpHandle(buf, len, &from);
c4ebc830 1124
eb9ae2f7 1125 commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);
1126}
1127
56714a1a 1128/*
1129 * ======================================================================
1130 * PUBLIC FUNCTIONS
1131 * ======================================================================
1132 */
1133
d5d466fc 1134void
1135htcpInit(void)
3340a3e6 1136{
775fa4ba 1137 if (Config.Port.htcp <= 0) {
62e76326 1138 debug(31, 1) ("HTCP Disabled.\n");
1139 return;
775fa4ba 1140 }
62e76326 1141
d5d466fc 1142 enter_suid();
1143 htcpInSocket = comm_open(SOCK_DGRAM,
bdb741f4 1144 IPPROTO_UDP,
62e76326 1145 Config.Addrs.udp_incoming,
1146 Config.Port.htcp,
1147 COMM_NONBLOCKING,
1148 "HTCP Socket");
d5d466fc 1149 leave_suid();
62e76326 1150
d5d466fc 1151 if (htcpInSocket < 0)
62e76326 1152 fatal("Cannot open HTCP Socket");
1153
d5d466fc 1154 commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
62e76326 1155
ba3eec6b 1156 debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.\n",
62e76326 1157 (int) Config.Port.htcp, htcpInSocket);
1158
d5d466fc 1159 if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) {
62e76326 1160 enter_suid();
1161 htcpOutSocket = comm_open(SOCK_DGRAM,
bdb741f4 1162 IPPROTO_UDP,
62e76326 1163 Config.Addrs.udp_outgoing,
1164 Config.Port.htcp,
1165 COMM_NONBLOCKING,
1166 "Outgoing HTCP Socket");
1167 leave_suid();
1168
1169 if (htcpOutSocket < 0)
1170 fatal("Cannot open Outgoing HTCP Socket");
1171
1172 commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
1173
1174 debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.\n",
1175 (int) Config.Port.htcp, htcpOutSocket);
1176
1177 fd_note(htcpInSocket, "Incoming HTCP socket");
d5d466fc 1178 } else {
62e76326 1179 htcpOutSocket = htcpInSocket;
d5d466fc 1180 }
62e76326 1181
e6ccf245 1182 if (!htcpDetailPool) {
b001e822 1183 htcpDetailPool = MemPools::GetInstance().create("htcpDetail", sizeof(htcpDetail));
675f3dff 1184 }
59c4d35b 1185}
72549e05 1186
56714a1a 1187void
190154cf 1188htcpQuery(StoreEntry * e, HttpRequest * req, peer * p)
56714a1a 1189{
26df9ec6 1190 cache_key *save_key;
56714a1a 1191 char *pkt;
1192 ssize_t pktlen;
1193 char vbuf[32];
1194 htcpStuff stuff;
75faaa7a 1195 HttpHeader hdr(hoRequest);
56714a1a 1196 Packer pa;
1197 MemBuf mb;
9c48373d 1198 http_state_flags flags;
775fa4ba 1199
1200 if (htcpInSocket < 0)
62e76326 1201 return;
775fa4ba 1202
9c48373d 1203 memset(&flags, '\0', sizeof(flags));
62e76326 1204
7af0a8e6 1205 snprintf(vbuf, sizeof(vbuf), "%d/%d",
62e76326 1206 req->http_ver.major, req->http_ver.minor);
1207
56714a1a 1208 stuff.op = HTCP_TST;
62e76326 1209
56714a1a 1210 stuff.rr = RR_REQUEST;
62e76326 1211
56714a1a 1212 stuff.f1 = 1;
62e76326 1213
56714a1a 1214 stuff.response = 0;
62e76326 1215
26df9ec6 1216 stuff.msg_id = ++msg_id_counter;
62e76326 1217
9c48373d 1218 stuff.S.method = (char *) RequestMethodStr[req->method];
62e76326 1219
9c48373d 1220 stuff.S.uri = (char *) storeUrl(e);
62e76326 1221
a2edf5dc 1222 stuff.S.version = vbuf;
62e76326 1223
3b0d7130 1224 HttpStateData::httpBuildRequestHeader(req, req, e, &hdr, flags);
62e76326 1225
2fe7eff9 1226 mb.init();
62e76326 1227
56714a1a 1228 packerToMemInit(&pa, &mb);
62e76326 1229
61f4f11b 1230 hdr.packInto(&pa);
62e76326 1231
519e0948 1232 hdr.clean();
62e76326 1233
56714a1a 1234 packerClean(&pa);
62e76326 1235
a2edf5dc 1236 stuff.S.req_hdrs = mb.buf;
62e76326 1237
56714a1a 1238 pkt = htcpBuildPacket(&stuff, &pktlen);
62e76326 1239
2fe7eff9 1240 mb.clean();
62e76326 1241
56714a1a 1242 if (pkt == NULL) {
62e76326 1243 debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n");
1244 return;
56714a1a 1245 }
62e76326 1246
56714a1a 1247 htcpSend(pkt, (int) pktlen, &p->in_addr);
26df9ec6 1248 save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS];
332dafa2 1249 storeKeyCopy(save_key, (const cache_key *)e->key);
d87ebd78 1250 debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key, storeKeyText(save_key));
3a3c723d 1251 xfree(pkt);
56714a1a 1252}
1253
62e76326 1254/*
72549e05 1255 * htcpSocketShutdown only closes the 'in' socket if it is
1256 * different than the 'out' socket.
1afe05c5 1257 */
72549e05 1258void
1259htcpSocketShutdown(void)
1afe05c5 1260{
72549e05 1261 if (htcpInSocket < 0)
62e76326 1262 return;
1263
1afe05c5 1264 if (htcpInSocket != htcpOutSocket) {
62e76326 1265 debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket);
1266 comm_close(htcpInSocket);
1afe05c5 1267 }
62e76326 1268
1269 /*
72549e05 1270 * Here we set 'htcpInSocket' to -1 even though the HTCP 'in'
1271 * and 'out' sockets might be just one FD. This prevents this
1272 * function from executing repeatedly. When we are really ready to
1273 * exit or restart, main will comm_close the 'out' descriptor.
1afe05c5 1274 */
72549e05 1275 htcpInSocket = -1;
62e76326 1276
1277 /*
72549e05 1278 * Normally we only write to the outgoing HTCP socket, but
1279 * we also have a read handler there to catch messages sent
1280 * to that specific interface. During shutdown, we must
1281 * disable reading on the outgoing socket.
1afe05c5 1282 */
675f3dff 1283 /* XXX Don't we need this handler to read replies while shutting down?
1284 * I think there should be a separate hander for reading replies..
1285 */
72549e05 1286 assert(htcpOutSocket > -1);
62e76326 1287
72549e05 1288 commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
1289}
1290
1afe05c5 1291void
72549e05 1292htcpSocketClose(void)
1293{
1294 htcpSocketShutdown();
62e76326 1295
72549e05 1296 if (htcpOutSocket > -1) {
62e76326 1297 debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket);
1298 comm_close(htcpOutSocket);
1299 htcpOutSocket = -1;
1afe05c5 1300 }
1301}