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