htcp.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:25k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: htcp.c,v 1.26 1998/10/08 20:10:21 wessels Exp $
  3.  *
  4.  * DEBUG: section 31    Hypertext Caching Protocol
  5.  * AUTHOR: Duane Wesssels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. typedef struct _Countstr Countstr;
  36. typedef struct _htcpHeader htcpHeader;
  37. typedef struct _htcpDataHeader htcpDataHeader;
  38. typedef struct _htcpAuthHeader htcpAuthHeader;
  39. typedef struct _htcpStuff htcpStuff;
  40. typedef struct _htcpSpecifier htcpSpecifier;
  41. typedef struct _htcpDetail htcpDetail;
  42. struct _Countstr {
  43.     u_short length;
  44.     char *text;
  45. };
  46. struct _htcpHeader {
  47.     u_short length;
  48.     u_char major;
  49.     u_char minor;
  50. };
  51. struct _htcpDataHeader {
  52.     u_short length;
  53. #if !WORDS_BIGENDIAN
  54.     u_char opcode:4;
  55.     u_char response:4;
  56. #else
  57.     u_char response:4;
  58.     u_char opcode:4;
  59. #endif
  60. #if !WORDS_BIGENDIAN
  61.     u_char reserved:6;
  62.     u_char F1:1;
  63.     u_char RR:1;
  64. #else
  65.     u_char RR:1;
  66.     u_char F1:1;
  67.     u_char reserved:6;
  68. #endif
  69.     u_num32 msg_id;
  70. };
  71.     /* RR == 0 --> F1 = RESPONSE DESIRED FLAG */
  72.     /* RR == 1 --> F1 = MESSAGE OVERALL FLAG */
  73.     /* RR == 0 --> REQUEST */
  74.     /* RR == 1 --> RESPONSE */
  75. struct _htcpAuthHeader {
  76.     u_short length;
  77.     time_t sig_time;
  78.     time_t sig_expire;
  79.     Countstr key_name;
  80.     Countstr signature;
  81. };
  82. struct _htcpSpecifier {
  83.     char *method;
  84.     char *uri;
  85.     char *version;
  86.     char *req_hdrs;
  87. };
  88. struct _htcpDetail {
  89.     char *resp_hdrs;
  90.     char *entity_hdrs;
  91.     char *cache_hdrs;
  92. };
  93. struct _htcpStuff {
  94.     int op;
  95.     int rr;
  96.     int f1;
  97.     int response;
  98.     u_num32 msg_id;
  99.     htcpSpecifier S;
  100.     htcpDetail D;
  101. };
  102. enum {
  103.     HTCP_NOP,
  104.     HTCP_TST,
  105.     HTCP_MON,
  106.     HTCP_SET,
  107.     HTCP_CLR,
  108.     HTCP_END
  109. };
  110. static const char *const htcpOpcodeStr[] =
  111. {
  112.     "HTCP_NOP",
  113.     "HTCP_TST",
  114.     "HTCP_MON",
  115.     "HTCP_SET",
  116.     "HTCP_CLR",
  117.     "HTCP_END"
  118. };
  119. /*
  120.  * values for htcpDataHeader->response
  121.  */
  122. enum {
  123.     AUTH_REQUIRED,
  124.     AUTH_FAILURE,
  125.     OPCODE_UNIMPLEMENTED,
  126.     MAJOR_VERSION_UNSUPPORTED,
  127.     MINOR_VERSION_UNSUPPORTED,
  128.     INVALID_OPCODE
  129. };
  130. /*
  131.  * values for htcpDataHeader->RR
  132.  */
  133. enum {
  134.     RR_REQUEST,
  135.     RR_RESPONSE
  136. };
  137. static u_num32 msg_id_counter = 0;
  138. static int htcpInSocket = -1;
  139. static int htcpOutSocket = -1;
  140. #define N_QUERIED_KEYS 256
  141. static cache_key queried_keys[N_QUERIED_KEYS][MD5_DIGEST_CHARS];
  142. static char *htcpBuildPacket(htcpStuff * stuff, ssize_t * len);
  143. static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz);
  144. static htcpDetail *htcpUnpackDetail(char *buf, int sz);
  145. static int htcpUnpackCountstr(char *buf, int sz, char **str);
  146. static ssize_t htcpBuildAuth(char *buf, size_t buflen);
  147. static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s);
  148. static ssize_t htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff);
  149. static ssize_t htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff);
  150. static ssize_t htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff);
  151. static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff);
  152. static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff);
  153. static void htcpFreeSpecifier(htcpSpecifier * s);
  154. static void htcpFreeDetail(htcpDetail * s);
  155. static void htcpHandle(char *buf, int sz, struct sockaddr_in *from);
  156. static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from);
  157. static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
  158. static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
  159. static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
  160. static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
  161. static void htcpRecv(int fd, void *data);
  162. static void htcpSend(const char *buf, int len, struct sockaddr_in *to);
  163. static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *);
  164. static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
  165. static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *);
  166. static void
  167. htcpHexdump(const char *tag, const char *s, int sz)
  168. {
  169. #if USE_HEXDUMP
  170.     int i;
  171.     int k;
  172.     char hex[80];
  173.     debug(31, 3) ("htcpHexdump %sn", tag);
  174.     memset(hex, '', 80);
  175.     for (i = 0; i < sz; i++) {
  176. k = i % 16;
  177. snprintf(&hex[k * 3], 4, " %02x", (int) *(s + i));
  178. if (k < 15 && i < (sz - 1))
  179.     continue;
  180. debug(31, 3) ("t%sn", hex);
  181. memset(hex, '', 80);
  182.     }
  183. #endif
  184. }
  185. /*
  186.  * STUFF FOR SENDING HTCP MESSAGES
  187.  */
  188. static ssize_t
  189. htcpBuildAuth(char *buf, size_t buflen)
  190. {
  191.     htcpAuthHeader auth;
  192.     size_t copy_sz = 0;
  193.     assert(2 == sizeof(u_short));
  194.     auth.length = htons(2);
  195.     copy_sz += 2;
  196.     assert(buflen >= copy_sz);
  197.     xmemcpy(buf, &auth, copy_sz);
  198.     return copy_sz;
  199. }
  200. static ssize_t
  201. htcpBuildCountstr(char *buf, size_t buflen, const char *s)
  202. {
  203.     u_short length;
  204.     size_t len;
  205.     off_t off = 0;
  206.     if (buflen - off < 2)
  207. return -1;
  208.     if (s)
  209. len = strlen(s);
  210.     else
  211. len = 0;
  212.     debug(31, 3) ("htcpBuildCountstr: LENGTH = %dn", len);
  213.     debug(31, 3) ("htcpBuildCountstr: TEXT = {%s}n", s ? s : "<NULL>");
  214.     length = htons((u_short) len);
  215.     xmemcpy(buf + off, &length, 2);
  216.     off += 2;
  217.     if (buflen - off < len)
  218. return -1;
  219.     if (len)
  220. xmemcpy(buf + off, s, len);
  221.     off += len;
  222.     return off;
  223. }
  224. static ssize_t
  225. htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff)
  226. {
  227.     ssize_t off = 0;
  228.     ssize_t s;
  229.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.method);
  230.     if (s < 0)
  231. return s;
  232.     off += s;
  233.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.uri);
  234.     if (s < 0)
  235. return s;
  236.     off += s;
  237.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.version);
  238.     if (s < 0)
  239. return s;
  240.     off += s;
  241.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.req_hdrs);
  242.     if (s < 0)
  243. return s;
  244.     off += s;
  245.     debug(31, 3) ("htcpBuildSpecifier: size %dn", (int) off);
  246.     return off;
  247. }
  248. static ssize_t
  249. htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff)
  250. {
  251.     ssize_t off = 0;
  252.     ssize_t s;
  253.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.resp_hdrs);
  254.     if (s < 0)
  255. return s;
  256.     off += s;
  257.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.entity_hdrs);
  258.     if (s < 0)
  259. return s;
  260.     off += s;
  261.     s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.cache_hdrs);
  262.     if (s < 0)
  263. return s;
  264.     off += s;
  265.     return off;
  266. }
  267. static ssize_t
  268. htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff)
  269. {
  270.     switch (stuff->rr) {
  271.     case RR_REQUEST:
  272. debug(31, 3) ("htcpBuildTstOpData: RR_REQUESTn");
  273. return htcpBuildSpecifier(buf, buflen, stuff);
  274.     case RR_RESPONSE:
  275. debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSEn");
  276. debug(31, 3) ("htcpBuildTstOpData: F1 = %dn", stuff->f1);
  277. if (stuff->f1) /* cache miss */
  278.     return 0;
  279. else /* cache hit */
  280.     return htcpBuildDetail(buf, buflen, stuff);
  281.     default:
  282. fatal_dump("htcpBuildTstOpData: bad RR value");
  283.     }
  284.     return 0;
  285. }
  286. static ssize_t
  287. htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff)
  288. {
  289.     ssize_t off = 0;
  290.     debug(31, 3) ("htcpBuildOpData: opcode %sn",
  291. htcpOpcodeStr[stuff->op]);
  292.     switch (stuff->op) {
  293.     case HTCP_TST:
  294. off = htcpBuildTstOpData(buf + off, buflen, stuff);
  295. break;
  296.     default:
  297. assert(0);
  298. break;
  299.     }
  300.     return off;
  301. }
  302. static ssize_t
  303. htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff)
  304. {
  305.     ssize_t off = 0;
  306.     ssize_t op_data_sz;
  307.     size_t hdr_sz = sizeof(htcpDataHeader);
  308.     htcpDataHeader hdr;
  309.     if (buflen < hdr_sz)
  310. return -1;
  311.     off += hdr_sz; /* skip! */
  312.     op_data_sz = htcpBuildOpData(buf + off, buflen - off, stuff);
  313.     if (op_data_sz < 0)
  314. return op_data_sz;
  315.     off += op_data_sz;
  316.     debug(31, 3) ("htcpBuildData: hdr.length = %dn", (int) off);
  317.     hdr.length = (u_short) off;
  318.     hdr.opcode = stuff->op;
  319.     hdr.response = stuff->response;
  320.     hdr.RR = stuff->rr;
  321.     hdr.F1 = stuff->f1;
  322.     hdr.msg_id = stuff->msg_id;
  323.     /* convert multi-byte fields */
  324.     hdr.length = htons(hdr.length);
  325.     hdr.msg_id = htonl(hdr.msg_id);
  326.     xmemcpy(buf, &hdr, hdr_sz);
  327.     debug(31, 3) ("htcpBuildData: size %dn", (int) off);
  328.     return off;
  329. }
  330. static char *
  331. htcpBuildPacket(htcpStuff * stuff, ssize_t * len)
  332. {
  333.     size_t buflen = 8192;
  334.     size_t s;
  335.     ssize_t off = 0;
  336.     size_t hdr_sz = sizeof(htcpHeader);
  337.     htcpHeader hdr;
  338.     char *buf = xcalloc(buflen, 1);
  339.     /* skip the header -- we don't know the overall length */
  340.     if (buflen < hdr_sz)
  341. return NULL;
  342.     off += hdr_sz;
  343.     s = htcpBuildData(buf + off, buflen - off, stuff);
  344.     if (s < 0)
  345. return NULL;
  346.     off += s;
  347.     s = htcpBuildAuth(buf + off, buflen - off);
  348.     if (s < 0)
  349. return NULL;
  350.     off += s;
  351.     hdr.length = htons((u_short) off);
  352.     hdr.major = 0;
  353.     hdr.minor = 0;
  354.     xmemcpy(buf, &hdr, hdr_sz);
  355.     *len = off;
  356.     debug(31, 3) ("htcpBuildPacket: size %dn", (int) off);
  357.     return buf;
  358. }
  359. static void
  360. htcpSend(const char *buf, int len, struct sockaddr_in *to)
  361. {
  362.     int x;
  363.     debug(31, 3) ("htcpSend: %s/%dn",
  364. inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port));
  365.     htcpHexdump("htcpSend", buf, len);
  366.     x = comm_udp_sendto(htcpOutSocket,
  367. to,
  368. sizeof(struct sockaddr_in),
  369. buf,
  370. len);
  371.     if (x < 0)
  372. debug(31, 0) ("htcpSend: FD %d sendto: %sn", htcpOutSocket, xstrerror());
  373. }
  374. /*
  375.  * STUFF FOR RECEIVING HTCP MESSAGES
  376.  */
  377. static void
  378. htcpFreeSpecifier(htcpSpecifier * s)
  379. {
  380.     safe_free(s->method);
  381.     safe_free(s->uri);
  382.     safe_free(s->version);
  383.     safe_free(s->req_hdrs);
  384.     xfree(s);
  385. }
  386. static void
  387. htcpFreeDetail(htcpDetail * d)
  388. {
  389.     safe_free(d->resp_hdrs);
  390.     safe_free(d->entity_hdrs);
  391.     safe_free(d->cache_hdrs);
  392.     xfree(d);
  393. }
  394. static int
  395. htcpUnpackCountstr(char *buf, int sz, char **str)
  396. {
  397.     u_short l;
  398.     debug(31, 3) ("htcpUnpackCountstr: sz = %dn", sz);
  399.     if (sz < 2) {
  400. debug(31, 3) ("htcpUnpackCountstr: sz < 2n");
  401. return -1;
  402.     }
  403.     htcpHexdump("htcpUnpackCountstr", buf, sz);
  404.     xmemcpy(&l, buf, 2);
  405.     l = ntohs(l);
  406.     buf += 2;
  407.     sz -= 2;
  408.     debug(31, 3) ("htcpUnpackCountstr: LENGTH = %dn", (int) l);
  409.     if (sz < l) {
  410. debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)n", sz, l);
  411. return -1;
  412.     }
  413.     if (str) {
  414. *str = xmalloc(l + 1);
  415. xstrncpy(*str, buf, l + 1);
  416. debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}n", *str);
  417.     }
  418.     return (int) l + 2;
  419. }
  420. static htcpSpecifier *
  421. htcpUnpackSpecifier(char *buf, int sz)
  422. {
  423.     htcpSpecifier *s = xcalloc(1, sizeof(htcpSpecifier));
  424.     int o;
  425.     debug(31, 3) ("htcpUnpackSpecifier: %d bytesn", (int) sz);
  426.     o = htcpUnpackCountstr(buf, sz, &s->method);
  427.     if (o < 0) {
  428. debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHODn");
  429. htcpFreeSpecifier(s);
  430. return NULL;
  431.     }
  432.     buf += o;
  433.     sz -= o;
  434.     o = htcpUnpackCountstr(buf, sz, &s->uri);
  435.     if (o < 0) {
  436. debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URIn");
  437. htcpFreeSpecifier(s);
  438. return NULL;
  439.     }
  440.     buf += o;
  441.     sz -= o;
  442.     o = htcpUnpackCountstr(buf, sz, &s->version);
  443.     if (o < 0) {
  444. debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSIONn");
  445. htcpFreeSpecifier(s);
  446. return NULL;
  447.     }
  448.     buf += o;
  449.     sz -= o;
  450.     o = htcpUnpackCountstr(buf, sz, &s->req_hdrs);
  451.     if (o < 0) {
  452. debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRSn");
  453. htcpFreeSpecifier(s);
  454. return NULL;
  455.     }
  456.     buf += o;
  457.     sz -= o;
  458.     debug(31, 3) ("htcpUnpackSpecifier: %d bytes leftn", sz);
  459.     return s;
  460. }
  461. static htcpDetail *
  462. htcpUnpackDetail(char *buf, int sz)
  463. {
  464.     htcpDetail *d = xcalloc(1, sizeof(htcpDetail));
  465.     int o;
  466.     debug(31, 3) ("htcpUnpackDetail: %d bytesn", (int) sz);
  467.     o = htcpUnpackCountstr(buf, sz, &d->resp_hdrs);
  468.     if (o < 0) {
  469. debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRSn");
  470. htcpFreeDetail(d);
  471. return NULL;
  472.     }
  473.     buf += o;
  474.     sz -= o;
  475.     o = htcpUnpackCountstr(buf, sz, &d->entity_hdrs);
  476.     if (o < 0) {
  477. debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRSn");
  478. htcpFreeDetail(d);
  479. return NULL;
  480.     }
  481.     buf += o;
  482.     sz -= o;
  483.     o = htcpUnpackCountstr(buf, sz, &d->cache_hdrs);
  484.     if (o < 0) {
  485. debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRSn");
  486. htcpFreeDetail(d);
  487. return NULL;
  488.     }
  489.     buf += o;
  490.     sz -= o;
  491.     debug(31, 3) ("htcpUnpackDetail: %d bytes leftn", sz);
  492.     return d;
  493. }
  494. static void
  495. htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from)
  496. {
  497.     htcpStuff stuff;
  498.     char *pkt;
  499.     HttpHeader hdr;
  500.     MemBuf mb;
  501.     Packer p;
  502.     ssize_t pktlen;
  503.     char *host;
  504.     int rtt = 0;
  505.     int hops = 0;
  506.     int samp = 0;
  507.     char cto_buf[128];
  508.     stuff.op = HTCP_TST;
  509.     stuff.rr = RR_RESPONSE;
  510.     stuff.f1 = 0;
  511.     stuff.response = e ? 0 : 1;
  512.     stuff.msg_id = dhdr->msg_id;
  513.     if (spec) {
  514. memBufDefInit(&mb);
  515. packerToMemInit(&p, &mb);
  516. httpHeaderInit(&hdr, hoHtcpReply);
  517. stuff.S.method = spec->method;
  518. stuff.S.uri = spec->uri;
  519. stuff.S.version = spec->version;
  520. stuff.S.req_hdrs = spec->req_hdrs;
  521. httpHeaderPutInt(&hdr, HDR_AGE,
  522.     e->timestamp <= squid_curtime ?
  523.     squid_curtime - e->timestamp : 0);
  524. httpHeaderPackInto(&hdr, &p);
  525. stuff.D.resp_hdrs = xstrdup(mb.buf);
  526. debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}n", stuff.D.resp_hdrs);
  527. memBufReset(&mb);
  528. httpHeaderReset(&hdr);
  529. if (e->expires > -1)
  530.     httpHeaderPutTime(&hdr, HDR_EXPIRES, e->expires);
  531. if (e->lastmod > -1)
  532.     httpHeaderPutTime(&hdr, HDR_LAST_MODIFIED, e->lastmod);
  533. httpHeaderPackInto(&hdr, &p);
  534. stuff.D.entity_hdrs = xstrdup(mb.buf);
  535. debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}n", stuff.D.entity_hdrs);
  536. memBufReset(&mb);
  537. httpHeaderReset(&hdr);
  538. if ((host = urlHostname(spec->uri))) {
  539.     netdbHostData(host, &samp, &rtt, &hops);
  540.     if (rtt || hops) {
  541. snprintf(cto_buf, 128, "%s %d %f %d",
  542.     host, samp, 0.001 * rtt, hops);
  543. httpHeaderPutExt(&hdr, "Cache-to-Origin", cto_buf);
  544.     }
  545. }
  546. httpHeaderPackInto(&hdr, &p);
  547. stuff.D.cache_hdrs = xstrdup(mb.buf);
  548. debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}n", stuff.D.cache_hdrs);
  549. memBufClean(&mb);
  550. httpHeaderClean(&hdr);
  551. packerClean(&p);
  552.     }
  553.     pkt = htcpBuildPacket(&stuff, &pktlen);
  554.     if (pkt == NULL) {
  555. debug(31, 0) ("htcpTstReply: htcpBuildPacket() failedn");
  556. return;
  557.     }
  558.     htcpSend(pkt, (int) pktlen, from);
  559.     xfree(pkt);
  560. }
  561. static void
  562. htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
  563. {
  564.     debug(31, 3) ("htcpHandleNop: Unimplementedn");
  565. }
  566. static void
  567. htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
  568. {
  569.     debug(31, 3) ("htcpHandleTst: sz = %dn", (int) sz);
  570.     if (hdr->RR == RR_REQUEST)
  571. htcpHandleTstRequest(hdr, buf, sz, from);
  572.     else
  573. htcpHandleTstResponse(hdr, buf, sz, from);
  574. }
  575. static void
  576. htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
  577. {
  578.     htcpReplyData htcpReply;
  579.     cache_key *key = NULL;
  580.     htcpDetail *d = NULL;
  581.     char *t;
  582.     if (hdr->F1 == 1) {
  583. debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1n");
  584. return;
  585.     }
  586.     memset(&htcpReply, '', sizeof(htcpReply));
  587.     httpHeaderInit(&htcpReply.hdr, hoHtcpReply);
  588.     htcpReply.msg_id = hdr->msg_id;
  589.     debug(31, 3) ("htcpHandleTstResponse: msg_id = %dn", (int) htcpReply.msg_id);
  590.     htcpReply.hit = hdr->response ? 0 : 1;
  591.     if (hdr->F1) {
  592. debug(31, 3) ("htcpHandleTstResponse: MISSn");
  593.     } else {
  594. debug(31, 3) ("htcpHandleTstResponse: HITn");
  595. d = htcpUnpackDetail(buf, sz);
  596. if (d == NULL) {
  597.     debug(31, 1) ("htcpHandleTstResponse: bad DETAILn");
  598.     return;
  599. }
  600. if ((t = d->resp_hdrs))
  601.     httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
  602. if ((t = d->entity_hdrs))
  603.     httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
  604. if ((t = d->cache_hdrs))
  605.     httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
  606.     }
  607.     key = queried_keys[htcpReply.msg_id % N_QUERIED_KEYS];
  608.     debug(31, 3) ("htcpHandleTstResponse: key (%p) %sn", key, storeKeyText(key));
  609.     neighborsHtcpReply(key, &htcpReply, from);
  610.     if (d)
  611. htcpFreeDetail(d);
  612. }
  613. static void
  614. htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from)
  615. {
  616.     /* buf should be a SPECIFIER */
  617.     htcpSpecifier *s;
  618.     StoreEntry *e;
  619.     method_t m;
  620.     if (sz == 0) {
  621. debug(31, 3) ("htcpHandleTst: nothing to don");
  622. return;
  623.     }
  624.     if (dhdr->F1 == 0)
  625. return;
  626.     s = htcpUnpackSpecifier(buf, sz);
  627.     if (NULL == s) {
  628. debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failedn");
  629. return;
  630.     }
  631.     debug(31, 3) ("htcpHandleTstRequest: %s %s %sn",
  632. s->method,
  633. s->uri,
  634. s->version);
  635.     m = urlParseMethod(s->method);
  636.     debug(31, 3) ("htcpHandleTstRequest: %sn", s->req_hdrs);
  637.     e = storeGetPublic(s->uri, m);
  638.     if (NULL == e) {
  639. /* cache miss */
  640. htcpTstReply(dhdr, NULL, NULL, from);
  641. #if WIP
  642.     } else if (!checkHeaders()) {
  643. /* refresh/other miss */
  644. htcpTstReply(dhdr, NULL, NULL, from);
  645. #endif
  646.     } else {
  647. /* hit */
  648. htcpTstReply(dhdr, e, s, from);
  649.     }
  650.     htcpFreeSpecifier(s);
  651. }
  652. static void
  653. htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
  654. {
  655.     debug(31, 3) ("htcpHandleMon: Unimplementedn");
  656. }
  657. static void
  658. htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
  659. {
  660.     debug(31, 3) ("htcpHandleSet: Unimplementedn");
  661. }
  662. static void
  663. htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
  664. {
  665.     htcpDataHeader hdr;
  666.     if (sz < sizeof(htcpDataHeader)) {
  667. debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader sizen");
  668. return;
  669.     }
  670.     xmemcpy(&hdr, buf, sizeof(htcpDataHeader));
  671.     hdr.length = ntohs(hdr.length);
  672.     hdr.msg_id = ntohl(hdr.msg_id);
  673.     debug(31, 3) ("htcpHandleData: sz = %dn", sz);
  674.     debug(31, 3) ("htcpHandleData: length = %dn", (int) hdr.length);
  675.     if (hdr.opcode > HTCP_END) {
  676. debug(31, 0) ("htcpHandleData: opcode %d out of rangen",
  677.     (int) hdr.opcode);
  678. return;
  679.     }
  680.     debug(31, 3) ("htcpHandleData: opcode = %d %sn",
  681. (int) hdr.opcode, htcpOpcodeStr[hdr.opcode]);
  682.     debug(31, 3) ("htcpHandleData: response = %dn", (int) hdr.response);
  683.     debug(31, 3) ("htcpHandleData: F1 = %dn", (int) hdr.F1);
  684.     debug(31, 3) ("htcpHandleData: RR = %dn", (int) hdr.RR);
  685.     debug(31, 3) ("htcpHandleData: msg_id = %dn", (int) hdr.msg_id);
  686.     if (sz < hdr.length) {
  687. debug(31, 0) ("htcpHandle: sz < hdr.lengthn");
  688. return;
  689.     }
  690.     /*
  691.      * set sz = hdr.length so we ignore any AUTH fields following
  692.      * the DATA.
  693.      */
  694.     sz = (int) hdr.length;
  695.     buf += sizeof(htcpDataHeader);
  696.     sz -= sizeof(htcpDataHeader);
  697.     debug(31, 3) ("htcpHandleData: sz = %dn", sz);
  698.     htcpHexdump("htcpHandleData", buf, sz);
  699.     switch (hdr.opcode) {
  700.     case HTCP_NOP:
  701. htcpHandleNop(&hdr, buf, sz, from);
  702. break;
  703.     case HTCP_TST:
  704. htcpHandleTst(&hdr, buf, sz, from);
  705. break;
  706.     case HTCP_MON:
  707. htcpHandleMon(&hdr, buf, sz, from);
  708. break;
  709.     case HTCP_SET:
  710. htcpHandleSet(&hdr, buf, sz, from);
  711. break;
  712.     default:
  713. assert(0);
  714. break;
  715.     }
  716. }
  717. static void
  718. htcpHandle(char *buf, int sz, struct sockaddr_in *from)
  719. {
  720.     htcpHeader htcpHdr;
  721.     if (sz < sizeof(htcpHeader)) {
  722. debug(31, 0) ("htcpHandle: msg size less than htcpHeader sizen");
  723. return;
  724.     }
  725.     htcpHexdump("htcpHandle", buf, sz);
  726.     xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
  727.     htcpHdr.length = ntohs(htcpHdr.length);
  728.     debug(31, 3) ("htcpHandle: htcpHdr.length = %dn", (int) htcpHdr.length);
  729.     debug(31, 3) ("htcpHandle: htcpHdr.major = %dn", (int) htcpHdr.major);
  730.     debug(31, 3) ("htcpHandle: htcpHdr.minor = %dn", (int) htcpHdr.minor);
  731.     if (sz != htcpHdr.length) {
  732. debug(31, 0) ("htcpHandle: sz != htcpHdr.lengthn");
  733. return;
  734.     }
  735.     buf += sizeof(htcpHeader);
  736.     sz -= sizeof(htcpHeader);
  737.     htcpHandleData(buf, sz, from);
  738. }
  739. static void
  740. htcpRecv(int fd, void *data)
  741. {
  742.     static char buf[8192];
  743.     int len;
  744.     static struct sockaddr_in from;
  745.     int flen = sizeof(struct sockaddr_in);
  746.     memset(&from, '', flen);
  747.     Counter.syscalls.sock.recvfroms++;
  748.     len = recvfrom(fd, buf, 8192, 0, (struct sockaddr *) &from, &flen);
  749.     debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%dn",
  750. fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
  751.     htcpHandle(buf, len, &from);
  752.     commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);
  753. }
  754. /*
  755.  * ======================================================================
  756.  * PUBLIC FUNCTIONS
  757.  * ======================================================================
  758.  */
  759. void
  760. htcpInit(void)
  761. {
  762.     enter_suid();
  763.     htcpInSocket = comm_open(SOCK_DGRAM,
  764. 0,
  765. Config.Addrs.udp_incoming,
  766. Config.Port.htcp,
  767. COMM_NONBLOCKING,
  768. "HTCP Socket");
  769.     leave_suid();
  770.     if (htcpInSocket < 0)
  771. fatal("Cannot open HTCP Socket");
  772.     commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
  773.     debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.n",
  774. (int) Config.Port.htcp, htcpInSocket);
  775.     if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) {
  776. enter_suid();
  777. htcpOutSocket = comm_open(SOCK_DGRAM,
  778.     0,
  779.     Config.Addrs.udp_outgoing,
  780.     Config.Port.htcp,
  781.     COMM_NONBLOCKING,
  782.     "Outgoing HTCP Socket");
  783. leave_suid();
  784. if (htcpOutSocket < 0)
  785.     fatal("Cannot open Outgoing HTCP Socket");
  786. commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
  787. debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.n",
  788.     (int) Config.Port.htcp, htcpOutSocket);
  789. fd_note(htcpInSocket, "Incoming HTCP socket");
  790.     } else {
  791. htcpOutSocket = htcpInSocket;
  792.     }
  793. }
  794. void
  795. htcpQuery(StoreEntry * e, request_t * req, peer * p)
  796. {
  797.     cache_key *save_key;
  798.     char *pkt;
  799.     ssize_t pktlen;
  800.     char vbuf[32];
  801.     htcpStuff stuff;
  802.     HttpHeader hdr;
  803.     Packer pa;
  804.     MemBuf mb;
  805.     http_state_flags flags;
  806.     memset(&flags, '', sizeof(flags));
  807.     snprintf(vbuf, sizeof(vbuf), "%3.1f", req->http_ver);
  808.     stuff.op = HTCP_TST;
  809.     stuff.rr = RR_REQUEST;
  810.     stuff.f1 = 1;
  811.     stuff.response = 0;
  812.     stuff.msg_id = ++msg_id_counter;
  813.     stuff.S.method = (char *) RequestMethodStr[req->method];
  814.     stuff.S.uri = (char *) storeUrl(e);
  815.     stuff.S.version = vbuf;
  816.     httpBuildRequestHeader(req, req, e, &hdr, -1, flags);
  817.     memBufDefInit(&mb);
  818.     packerToMemInit(&pa, &mb);
  819.     httpHeaderPackInto(&hdr, &pa);
  820.     httpHeaderClean(&hdr);
  821.     packerClean(&pa);
  822.     stuff.S.req_hdrs = mb.buf;
  823.     pkt = htcpBuildPacket(&stuff, &pktlen);
  824.     if (pkt == NULL) {
  825. debug(31, 0) ("htcpQuery: htcpBuildPacket() failedn");
  826. return;
  827.     }
  828.     htcpSend(pkt, (int) pktlen, &p->in_addr);
  829.     save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS];
  830.     storeKeyCopy(save_key, e->key);
  831.     debug(31, 3) ("htcpQuery: key (%p) %sn", save_key, storeKeyText(save_key));
  832.     xfree(pkt);
  833. }
  834. /*  
  835.  * htcpSocketShutdown only closes the 'in' socket if it is
  836.  * different than the 'out' socket.
  837.  */
  838. void
  839. htcpSocketShutdown(void)
  840. {
  841.     if (htcpInSocket < 0)
  842. return;
  843.     if (htcpInSocket != htcpOutSocket) {
  844. debug(12, 1) ("FD %d Closing HTCP socketn", htcpInSocket);
  845. comm_close(htcpInSocket);
  846.     }
  847.     /*      
  848.      * Here we set 'htcpInSocket' to -1 even though the HTCP 'in'
  849.      * and 'out' sockets might be just one FD.  This prevents this
  850.      * function from executing repeatedly.  When we are really ready to
  851.      * exit or restart, main will comm_close the 'out' descriptor.
  852.      */
  853.     htcpInSocket = -1;
  854.     /*      
  855.      * Normally we only write to the outgoing HTCP socket, but
  856.      * we also have a read handler there to catch messages sent
  857.      * to that specific interface.  During shutdown, we must
  858.      * disable reading on the outgoing socket.
  859.      */
  860.     assert(htcpOutSocket > -1);
  861.     commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
  862. }
  863. void
  864. htcpSocketClose(void)
  865. {
  866.     htcpSocketShutdown();
  867.     if (htcpOutSocket > -1) {
  868. debug(12, 1) ("FD %d Closing HTCP socketn", htcpOutSocket);
  869. comm_close(htcpOutSocket);
  870.     }
  871. }