3 * $Id: htcp.cc,v 1.34 2001/01/12 00:37:18 wessels Exp $
5 * DEBUG: section 31 Hypertext Caching Protocol
6 * AUTHOR: Duane Wesssels
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
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.
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.
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.
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.
38 typedef struct _Countstr Countstr
;
39 typedef struct _htcpHeader htcpHeader
;
40 typedef struct _htcpDataHeader htcpDataHeader
;
41 typedef struct _htcpAuthHeader htcpAuthHeader
;
42 typedef struct _htcpStuff htcpStuff
;
43 typedef struct _htcpSpecifier htcpSpecifier
;
44 typedef struct _htcpDetail htcpDetail
;
57 struct _htcpDataHeader
{
60 unsigned int opcode
:4;
61 unsigned int response
:4;
63 unsigned int response
:4;
64 unsigned int opcode
:4;
67 unsigned int reserved
:6;
73 unsigned int reserved
:6;
78 /* RR == 0 --> F1 = RESPONSE DESIRED FLAG */
79 /* RR == 1 --> F1 = MESSAGE OVERALL FLAG */
80 /* RR == 0 --> REQUEST */
81 /* RR == 1 --> RESPONSE */
83 struct _htcpAuthHeader
{
91 struct _htcpSpecifier
{
123 static const char *const htcpOpcodeStr
[] =
134 * values for htcpDataHeader->response
139 OPCODE_UNIMPLEMENTED
,
140 MAJOR_VERSION_UNSUPPORTED
,
141 MINOR_VERSION_UNSUPPORTED
,
146 * values for htcpDataHeader->RR
153 static u_num32 msg_id_counter
= 0;
154 static int htcpInSocket
= -1;
155 static int htcpOutSocket
= -1;
156 #define N_QUERIED_KEYS 256
157 static cache_key queried_keys
[N_QUERIED_KEYS
][MD5_DIGEST_CHARS
];
159 static char *htcpBuildPacket(htcpStuff
* stuff
, ssize_t
* len
);
160 static htcpSpecifier
*htcpUnpackSpecifier(char *buf
, int sz
);
161 static htcpDetail
*htcpUnpackDetail(char *buf
, int sz
);
162 static int htcpUnpackCountstr(char *buf
, int sz
, char **str
);
163 static ssize_t
htcpBuildAuth(char *buf
, size_t buflen
);
164 static ssize_t
htcpBuildCountstr(char *buf
, size_t buflen
, const char *s
);
165 static ssize_t
htcpBuildData(char *buf
, size_t buflen
, htcpStuff
* stuff
);
166 static ssize_t
htcpBuildDetail(char *buf
, size_t buflen
, htcpStuff
* stuff
);
167 static ssize_t
htcpBuildOpData(char *buf
, size_t buflen
, htcpStuff
* stuff
);
168 static ssize_t
htcpBuildSpecifier(char *buf
, size_t buflen
, htcpStuff
* stuff
);
169 static ssize_t
htcpBuildTstOpData(char *buf
, size_t buflen
, htcpStuff
* stuff
);
170 static void htcpFreeSpecifier(htcpSpecifier
* s
);
171 static void htcpFreeDetail(htcpDetail
* s
);
172 static void htcpHandle(char *buf
, int sz
, struct sockaddr_in
*from
);
173 static void htcpHandleData(char *buf
, int sz
, struct sockaddr_in
*from
);
174 static void htcpHandleMon(htcpDataHeader
*, char *buf
, int sz
, struct sockaddr_in
*from
);
175 static void htcpHandleNop(htcpDataHeader
*, char *buf
, int sz
, struct sockaddr_in
*from
);
176 static void htcpHandleSet(htcpDataHeader
*, char *buf
, int sz
, struct sockaddr_in
*from
);
177 static void htcpHandleTst(htcpDataHeader
*, char *buf
, int sz
, struct sockaddr_in
*from
);
178 static void htcpRecv(int fd
, void *data
);
179 static void htcpSend(const char *buf
, int len
, struct sockaddr_in
*to
);
180 static void htcpTstReply(htcpDataHeader
*, StoreEntry
*, htcpSpecifier
*, struct sockaddr_in
*);
181 static void htcpHandleTstRequest(htcpDataHeader
*, char *buf
, int sz
, struct sockaddr_in
*from
);
182 static void htcpHandleTstResponse(htcpDataHeader
*, char *, int, struct sockaddr_in
*);
183 static StoreEntry
*htcpCheckHit(const htcpSpecifier
*);
186 htcpHexdump(const char *tag
, const char *s
, int sz
)
192 debug(31, 3) ("htcpHexdump %s\n", tag
);
193 memset(hex
, '\0', 80);
194 for (i
= 0; i
< sz
; i
++) {
196 snprintf(&hex
[k
* 3], 4, " %02x", (int) *(s
+ i
));
197 if (k
< 15 && i
< (sz
- 1))
199 debug(31, 3) ("\t%s\n", hex
);
200 memset(hex
, '\0', 80);
206 * STUFF FOR SENDING HTCP MESSAGES
210 htcpBuildAuth(char *buf
, size_t buflen
)
214 assert(2 == sizeof(u_short
));
215 auth
.length
= htons(2);
217 assert(buflen
>= copy_sz
);
218 xmemcpy(buf
, &auth
, copy_sz
);
223 htcpBuildCountstr(char *buf
, size_t buflen
, const char *s
)
228 if (buflen
- off
< 2)
234 debug(31, 3) ("htcpBuildCountstr: LENGTH = %d\n", len
);
235 debug(31, 3) ("htcpBuildCountstr: TEXT = {%s}\n", s
? s
: "<NULL>");
236 length
= htons((u_short
) len
);
237 xmemcpy(buf
+ off
, &length
, 2);
239 if (buflen
- off
< len
)
242 xmemcpy(buf
+ off
, s
, len
);
248 htcpBuildSpecifier(char *buf
, size_t buflen
, htcpStuff
* stuff
)
252 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->S
.method
);
256 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->S
.uri
);
260 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->S
.version
);
264 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->S
.req_hdrs
);
268 debug(31, 3) ("htcpBuildSpecifier: size %d\n", (int) off
);
273 htcpBuildDetail(char *buf
, size_t buflen
, htcpStuff
* stuff
)
277 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->D
.resp_hdrs
);
281 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->D
.entity_hdrs
);
285 s
= htcpBuildCountstr(buf
+ off
, buflen
- off
, stuff
->D
.cache_hdrs
);
293 htcpBuildTstOpData(char *buf
, size_t buflen
, htcpStuff
* stuff
)
297 debug(31, 3) ("htcpBuildTstOpData: RR_REQUEST\n");
298 return htcpBuildSpecifier(buf
, buflen
, stuff
);
300 debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSE\n");
301 debug(31, 3) ("htcpBuildTstOpData: F1 = %d\n", stuff
->f1
);
302 if (stuff
->f1
) /* cache miss */
305 return htcpBuildDetail(buf
, buflen
, stuff
);
307 fatal_dump("htcpBuildTstOpData: bad RR value");
313 htcpBuildOpData(char *buf
, size_t buflen
, htcpStuff
* stuff
)
316 debug(31, 3) ("htcpBuildOpData: opcode %s\n",
317 htcpOpcodeStr
[stuff
->op
]);
320 off
= htcpBuildTstOpData(buf
+ off
, buflen
, stuff
);
330 htcpBuildData(char *buf
, size_t buflen
, htcpStuff
* stuff
)
334 size_t hdr_sz
= sizeof(htcpDataHeader
);
338 off
+= hdr_sz
; /* skip! */
339 op_data_sz
= htcpBuildOpData(buf
+ off
, buflen
- off
, stuff
);
343 debug(31, 3) ("htcpBuildData: hdr.length = %d\n", (int) off
);
344 hdr
.length
= (u_short
) off
;
345 hdr
.opcode
= stuff
->op
;
346 hdr
.response
= stuff
->response
;
349 hdr
.msg_id
= stuff
->msg_id
;
350 /* convert multi-byte fields */
351 hdr
.length
= htons(hdr
.length
);
352 hdr
.msg_id
= htonl(hdr
.msg_id
);
353 xmemcpy(buf
, &hdr
, hdr_sz
);
354 debug(31, 3) ("htcpBuildData: size %d\n", (int) off
);
359 htcpBuildPacket(htcpStuff
* stuff
, ssize_t
* len
)
361 size_t buflen
= 8192;
364 size_t hdr_sz
= sizeof(htcpHeader
);
366 char *buf
= xcalloc(buflen
, 1);
367 /* skip the header -- we don't know the overall length */
368 if (buflen
< hdr_sz
) {
373 s
= htcpBuildData(buf
+ off
, buflen
- off
, stuff
);
379 s
= htcpBuildAuth(buf
+ off
, buflen
- off
);
385 hdr
.length
= htons((u_short
) off
);
388 xmemcpy(buf
, &hdr
, hdr_sz
);
390 debug(31, 3) ("htcpBuildPacket: size %d\n", (int) off
);
395 htcpSend(const char *buf
, int len
, struct sockaddr_in
*to
)
398 debug(31, 3) ("htcpSend: %s/%d\n",
399 inet_ntoa(to
->sin_addr
), (int) ntohs(to
->sin_port
));
400 htcpHexdump("htcpSend", buf
, len
);
401 x
= comm_udp_sendto(htcpOutSocket
,
403 sizeof(struct sockaddr_in
),
407 debug(31, 0) ("htcpSend: FD %d sendto: %s\n", htcpOutSocket
, xstrerror());
411 * STUFF FOR RECEIVING HTCP MESSAGES
415 htcpFreeSpecifier(htcpSpecifier
* s
)
417 safe_free(s
->method
);
419 safe_free(s
->version
);
420 safe_free(s
->req_hdrs
);
421 memFree(s
, MEM_HTCP_SPECIFIER
);
425 htcpFreeDetail(htcpDetail
* d
)
427 safe_free(d
->resp_hdrs
);
428 safe_free(d
->entity_hdrs
);
429 safe_free(d
->cache_hdrs
);
430 memFree(d
, MEM_HTCP_DETAIL
);
434 htcpUnpackCountstr(char *buf
, int sz
, char **str
)
437 debug(31, 3) ("htcpUnpackCountstr: sz = %d\n", sz
);
439 debug(31, 3) ("htcpUnpackCountstr: sz < 2\n");
442 htcpHexdump("htcpUnpackCountstr", buf
, sz
);
447 debug(31, 3) ("htcpUnpackCountstr: LENGTH = %d\n", (int) l
);
449 debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz
, l
);
453 *str
= xmalloc(l
+ 1);
454 xstrncpy(*str
, buf
, l
+ 1);
455 debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str
);
460 static htcpSpecifier
*
461 htcpUnpackSpecifier(char *buf
, int sz
)
463 htcpSpecifier
*s
= memAllocate(MEM_HTCP_SPECIFIER
);
465 debug(31, 3) ("htcpUnpackSpecifier: %d bytes\n", (int) sz
);
466 o
= htcpUnpackCountstr(buf
, sz
, &s
->method
);
468 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
469 htcpFreeSpecifier(s
);
474 o
= htcpUnpackCountstr(buf
, sz
, &s
->uri
);
476 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n");
477 htcpFreeSpecifier(s
);
482 o
= htcpUnpackCountstr(buf
, sz
, &s
->version
);
484 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n");
485 htcpFreeSpecifier(s
);
490 o
= htcpUnpackCountstr(buf
, sz
, &s
->req_hdrs
);
492 debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n");
493 htcpFreeSpecifier(s
);
498 debug(31, 3) ("htcpUnpackSpecifier: %d bytes left\n", sz
);
503 htcpUnpackDetail(char *buf
, int sz
)
505 htcpDetail
*d
= memAllocate(MEM_HTCP_DETAIL
);
507 debug(31, 3) ("htcpUnpackDetail: %d bytes\n", (int) sz
);
508 o
= htcpUnpackCountstr(buf
, sz
, &d
->resp_hdrs
);
510 debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n");
516 o
= htcpUnpackCountstr(buf
, sz
, &d
->entity_hdrs
);
518 debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n");
524 o
= htcpUnpackCountstr(buf
, sz
, &d
->cache_hdrs
);
526 debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n");
532 debug(31, 3) ("htcpUnpackDetail: %d bytes left\n", sz
);
537 htcpTstReply(htcpDataHeader
* dhdr
, StoreEntry
* e
, htcpSpecifier
* spec
, struct sockaddr_in
*from
)
550 memset(&stuff
, '\0', sizeof(stuff
));
552 stuff
.rr
= RR_RESPONSE
;
554 stuff
.response
= e
? 0 : 1;
555 debug(31, 3) ("htcpTstReply: response = %d\n", stuff
.response
);
556 stuff
.msg_id
= dhdr
->msg_id
;
559 packerToMemInit(&p
, &mb
);
560 httpHeaderInit(&hdr
, hoHtcpReply
);
561 stuff
.S
.method
= spec
->method
;
562 stuff
.S
.uri
= spec
->uri
;
563 stuff
.S
.version
= spec
->version
;
564 stuff
.S
.req_hdrs
= spec
->req_hdrs
;
565 httpHeaderPutInt(&hdr
, HDR_AGE
,
566 e
->timestamp
<= squid_curtime
?
567 squid_curtime
- e
->timestamp
: 0);
568 httpHeaderPackInto(&hdr
, &p
);
569 stuff
.D
.resp_hdrs
= xstrdup(mb
.buf
);
570 debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}\n", stuff
.D
.resp_hdrs
);
572 httpHeaderReset(&hdr
);
574 httpHeaderPutTime(&hdr
, HDR_EXPIRES
, e
->expires
);
576 httpHeaderPutTime(&hdr
, HDR_LAST_MODIFIED
, e
->lastmod
);
577 httpHeaderPackInto(&hdr
, &p
);
578 stuff
.D
.entity_hdrs
= xstrdup(mb
.buf
);
579 debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}\n", stuff
.D
.entity_hdrs
);
581 httpHeaderReset(&hdr
);
582 if ((host
= urlHostname(spec
->uri
))) {
583 netdbHostData(host
, &samp
, &rtt
, &hops
);
585 snprintf(cto_buf
, 128, "%s %d %f %d",
586 host
, samp
, 0.001 * rtt
, hops
);
587 httpHeaderPutExt(&hdr
, "Cache-to-Origin", cto_buf
);
590 httpHeaderPackInto(&hdr
, &p
);
591 stuff
.D
.cache_hdrs
= xstrdup(mb
.buf
);
592 debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}\n", stuff
.D
.cache_hdrs
);
594 httpHeaderClean(&hdr
);
597 pkt
= htcpBuildPacket(&stuff
, &pktlen
);
599 debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n");
602 htcpSend(pkt
, (int) pktlen
, from
);
607 htcpHandleNop(htcpDataHeader
* hdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
609 debug(31, 3) ("htcpHandleNop: Unimplemented\n");
613 htcpCheckHit(const htcpSpecifier
* s
)
616 method_t m
= urlParseMethod(s
->method
);
617 StoreEntry
*e
= storeGetPublic(s
->uri
, m
);
620 debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
623 if (!storeEntryValidToSend(e
)) {
624 debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
627 request
= urlParse(m
, s
->uri
);
628 if (NULL
== request
) {
629 debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
632 blk_end
= s
->req_hdrs
+ strlen(s
->req_hdrs
);
633 if (!httpHeaderParse(&request
->header
, s
->req_hdrs
, blk_end
)) {
634 debug(31, 3) ("htcpCheckHit: NO; failed to parse request headers\n");
636 } else if (refreshCheckHTCP(e
, request
)) {
637 debug(31, 3) ("htcpCheckHit: NO; cached response is stale\n");
640 debug(31, 3) ("htcpCheckHit: YES!?\n");
642 requestDestroy(request
);
647 htcpHandleTst(htcpDataHeader
* hdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
649 debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz
);
650 if (hdr
->RR
== RR_REQUEST
)
651 htcpHandleTstRequest(hdr
, buf
, sz
, from
);
653 htcpHandleTstResponse(hdr
, buf
, sz
, from
);
657 htcpHandleTstResponse(htcpDataHeader
* hdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
659 htcpReplyData htcpReply
;
660 cache_key
*key
= NULL
;
661 htcpDetail
*d
= NULL
;
664 debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
667 memset(&htcpReply
, '\0', sizeof(htcpReply
));
668 httpHeaderInit(&htcpReply
.hdr
, hoHtcpReply
);
669 htcpReply
.msg_id
= hdr
->msg_id
;
670 debug(31, 3) ("htcpHandleTstResponse: msg_id = %d\n", (int) htcpReply
.msg_id
);
671 htcpReply
.hit
= hdr
->response
? 0 : 1;
673 debug(31, 3) ("htcpHandleTstResponse: MISS\n");
675 debug(31, 3) ("htcpHandleTstResponse: HIT\n");
676 d
= htcpUnpackDetail(buf
, sz
);
678 debug(31, 1) ("htcpHandleTstResponse: bad DETAIL\n");
681 if ((t
= d
->resp_hdrs
))
682 httpHeaderParse(&htcpReply
.hdr
, t
, t
+ strlen(t
));
683 if ((t
= d
->entity_hdrs
))
684 httpHeaderParse(&htcpReply
.hdr
, t
, t
+ strlen(t
));
685 if ((t
= d
->cache_hdrs
))
686 httpHeaderParse(&htcpReply
.hdr
, t
, t
+ strlen(t
));
688 key
= queried_keys
[htcpReply
.msg_id
% N_QUERIED_KEYS
];
689 debug(31, 3) ("htcpHandleTstResponse: key (%p) %s\n", key
, storeKeyText(key
));
690 neighborsHtcpReply(key
, &htcpReply
, from
);
691 httpHeaderClean(&htcpReply
.hdr
);
697 htcpHandleTstRequest(htcpDataHeader
* dhdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
699 /* buf should be a SPECIFIER */
703 debug(31, 3) ("htcpHandleTst: nothing to do\n");
708 s
= htcpUnpackSpecifier(buf
, sz
);
710 debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
713 debug(31, 3) ("htcpHandleTstRequest: %s %s %s\n",
717 debug(31, 3) ("htcpHandleTstRequest: %s\n", s
->req_hdrs
);
718 if ((e
= htcpCheckHit(s
)))
719 htcpTstReply(dhdr
, e
, s
, from
); /* hit */
721 htcpTstReply(dhdr
, NULL
, NULL
, from
); /* cache miss */
722 htcpFreeSpecifier(s
);
726 htcpHandleMon(htcpDataHeader
* hdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
728 debug(31, 3) ("htcpHandleMon: Unimplemented\n");
732 htcpHandleSet(htcpDataHeader
* hdr
, char *buf
, int sz
, struct sockaddr_in
*from
)
734 debug(31, 3) ("htcpHandleSet: Unimplemented\n");
738 htcpHandleData(char *buf
, int sz
, struct sockaddr_in
*from
)
741 if (sz
< sizeof(htcpDataHeader
)) {
742 debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader size\n");
745 xmemcpy(&hdr
, buf
, sizeof(htcpDataHeader
));
746 hdr
.length
= ntohs(hdr
.length
);
747 hdr
.msg_id
= ntohl(hdr
.msg_id
);
748 debug(31, 3) ("htcpHandleData: sz = %d\n", sz
);
749 debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr
.length
);
750 if (hdr
.opcode
> HTCP_END
) {
751 debug(31, 0) ("htcpHandleData: opcode %d out of range\n",
755 debug(31, 3) ("htcpHandleData: opcode = %d %s\n",
756 (int) hdr
.opcode
, htcpOpcodeStr
[hdr
.opcode
]);
757 debug(31, 3) ("htcpHandleData: response = %d\n", (int) hdr
.response
);
758 debug(31, 3) ("htcpHandleData: F1 = %d\n", (int) hdr
.F1
);
759 debug(31, 3) ("htcpHandleData: RR = %d\n", (int) hdr
.RR
);
760 debug(31, 3) ("htcpHandleData: msg_id = %d\n", (int) hdr
.msg_id
);
761 if (sz
< hdr
.length
) {
762 debug(31, 0) ("htcpHandle: sz < hdr.length\n");
766 * set sz = hdr.length so we ignore any AUTH fields following
769 sz
= (int) hdr
.length
;
770 buf
+= sizeof(htcpDataHeader
);
771 sz
-= sizeof(htcpDataHeader
);
772 debug(31, 3) ("htcpHandleData: sz = %d\n", sz
);
773 htcpHexdump("htcpHandleData", buf
, sz
);
774 switch (hdr
.opcode
) {
776 htcpHandleNop(&hdr
, buf
, sz
, from
);
779 htcpHandleTst(&hdr
, buf
, sz
, from
);
782 htcpHandleMon(&hdr
, buf
, sz
, from
);
785 htcpHandleSet(&hdr
, buf
, sz
, from
);
794 htcpHandle(char *buf
, int sz
, struct sockaddr_in
*from
)
797 if (sz
< sizeof(htcpHeader
)) {
798 debug(31, 0) ("htcpHandle: msg size less than htcpHeader size\n");
801 htcpHexdump("htcpHandle", buf
, sz
);
802 xmemcpy(&htcpHdr
, buf
, sizeof(htcpHeader
));
803 htcpHdr
.length
= ntohs(htcpHdr
.length
);
804 debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr
.length
);
805 debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr
.major
);
806 debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr
.minor
);
807 if (sz
!= htcpHdr
.length
) {
808 debug(31, 1) ("htcpHandle: sz != htcpHdr.length\n");
811 buf
+= sizeof(htcpHeader
);
812 sz
-= sizeof(htcpHeader
);
813 htcpHandleData(buf
, sz
, from
);
817 htcpRecv(int fd
, void *data
)
819 static char buf
[8192];
821 static struct sockaddr_in from
;
822 int flen
= sizeof(struct sockaddr_in
);
823 memset(&from
, '\0', flen
);
824 statCounter
.syscalls
.sock
.recvfroms
++;
825 len
= recvfrom(fd
, buf
, 8192, 0, (struct sockaddr
*) &from
, &flen
);
826 debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n",
827 fd
, len
, inet_ntoa(from
.sin_addr
), ntohs(from
.sin_port
));
828 htcpHandle(buf
, len
, &from
);
829 commSetSelect(fd
, COMM_SELECT_READ
, htcpRecv
, NULL
, 0);
833 * ======================================================================
835 * ======================================================================
842 htcpInSocket
= comm_open(SOCK_DGRAM
,
844 Config
.Addrs
.udp_incoming
,
849 if (htcpInSocket
< 0)
850 fatal("Cannot open HTCP Socket");
851 commSetSelect(htcpInSocket
, COMM_SELECT_READ
, htcpRecv
, NULL
, 0);
852 debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.\n",
853 (int) Config
.Port
.htcp
, htcpInSocket
);
854 if (Config
.Addrs
.udp_outgoing
.s_addr
!= no_addr
.s_addr
) {
856 htcpOutSocket
= comm_open(SOCK_DGRAM
,
858 Config
.Addrs
.udp_outgoing
,
861 "Outgoing HTCP Socket");
863 if (htcpOutSocket
< 0)
864 fatal("Cannot open Outgoing HTCP Socket");
865 commSetSelect(htcpOutSocket
, COMM_SELECT_READ
, htcpRecv
, NULL
, 0);
866 debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.\n",
867 (int) Config
.Port
.htcp
, htcpOutSocket
);
868 fd_note(htcpInSocket
, "Incoming HTCP socket");
870 htcpOutSocket
= htcpInSocket
;
872 memDataInit(MEM_HTCP_SPECIFIER
, "htcpSpecifier", sizeof(htcpSpecifier
), 0);
873 memDataInit(MEM_HTCP_DETAIL
, "htcpDetail", sizeof(htcpDetail
), 0);
877 htcpQuery(StoreEntry
* e
, request_t
* req
, peer
* p
)
887 http_state_flags flags
;
888 memset(&flags
, '\0', sizeof(flags
));
889 snprintf(vbuf
, sizeof(vbuf
), "%d/%d",
890 req
->http_ver
.major
, req
->http_ver
.minor
);
892 stuff
.rr
= RR_REQUEST
;
895 stuff
.msg_id
= ++msg_id_counter
;
896 stuff
.S
.method
= (char *) RequestMethodStr
[req
->method
];
897 stuff
.S
.uri
= (char *) storeUrl(e
);
898 stuff
.S
.version
= vbuf
;
899 httpBuildRequestHeader(req
, req
, e
, &hdr
, -1, flags
);
901 packerToMemInit(&pa
, &mb
);
902 httpHeaderPackInto(&hdr
, &pa
);
903 httpHeaderClean(&hdr
);
905 stuff
.S
.req_hdrs
= mb
.buf
;
906 pkt
= htcpBuildPacket(&stuff
, &pktlen
);
909 debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n");
912 htcpSend(pkt
, (int) pktlen
, &p
->in_addr
);
913 save_key
= queried_keys
[stuff
.msg_id
% N_QUERIED_KEYS
];
914 storeKeyCopy(save_key
, e
->hash
.key
);
915 debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key
, storeKeyText(save_key
));
920 * htcpSocketShutdown only closes the 'in' socket if it is
921 * different than the 'out' socket.
924 htcpSocketShutdown(void)
926 if (htcpInSocket
< 0)
928 if (htcpInSocket
!= htcpOutSocket
) {
929 debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket
);
930 comm_close(htcpInSocket
);
933 * Here we set 'htcpInSocket' to -1 even though the HTCP 'in'
934 * and 'out' sockets might be just one FD. This prevents this
935 * function from executing repeatedly. When we are really ready to
936 * exit or restart, main will comm_close the 'out' descriptor.
940 * Normally we only write to the outgoing HTCP socket, but
941 * we also have a read handler there to catch messages sent
942 * to that specific interface. During shutdown, we must
943 * disable reading on the outgoing socket.
945 assert(htcpOutSocket
> -1);
946 commSetSelect(htcpOutSocket
, COMM_SELECT_READ
, NULL
, NULL
, 0);
950 htcpSocketClose(void)
952 htcpSocketShutdown();
953 if (htcpOutSocket
> -1) {
954 debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket
);
955 comm_close(htcpOutSocket
);