📄 htcp.c
字号:
/* * $Id: htcp.c,v 1.26 1998/10/08 20:10:21 wessels Exp $ * * DEBUG: section 31 Hypertext Caching Protocol * AUTHOR: Duane Wesssels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"typedef struct _Countstr Countstr;typedef struct _htcpHeader htcpHeader;typedef struct _htcpDataHeader htcpDataHeader;typedef struct _htcpAuthHeader htcpAuthHeader;typedef struct _htcpStuff htcpStuff;typedef struct _htcpSpecifier htcpSpecifier;typedef struct _htcpDetail htcpDetail;struct _Countstr { u_short length; char *text;};struct _htcpHeader { u_short length; u_char major; u_char minor;};struct _htcpDataHeader { u_short length;#if !WORDS_BIGENDIAN u_char opcode:4; u_char response:4;#else u_char response:4; u_char opcode:4;#endif#if !WORDS_BIGENDIAN u_char reserved:6; u_char F1:1; u_char RR:1;#else u_char RR:1; u_char F1:1; u_char reserved:6;#endif u_num32 msg_id;}; /* RR == 0 --> F1 = RESPONSE DESIRED FLAG */ /* RR == 1 --> F1 = MESSAGE OVERALL FLAG */ /* RR == 0 --> REQUEST */ /* RR == 1 --> RESPONSE */struct _htcpAuthHeader { u_short length; time_t sig_time; time_t sig_expire; Countstr key_name; Countstr signature;};struct _htcpSpecifier { char *method; char *uri; char *version; char *req_hdrs;};struct _htcpDetail { char *resp_hdrs; char *entity_hdrs; char *cache_hdrs;};struct _htcpStuff { int op; int rr; int f1; int response; u_num32 msg_id; htcpSpecifier S; htcpDetail D;};enum { HTCP_NOP, HTCP_TST, HTCP_MON, HTCP_SET, HTCP_CLR, HTCP_END};static const char *const htcpOpcodeStr[] ={ "HTCP_NOP", "HTCP_TST", "HTCP_MON", "HTCP_SET", "HTCP_CLR", "HTCP_END"};/* * values for htcpDataHeader->response */enum { AUTH_REQUIRED, AUTH_FAILURE, OPCODE_UNIMPLEMENTED, MAJOR_VERSION_UNSUPPORTED, MINOR_VERSION_UNSUPPORTED, INVALID_OPCODE};/* * values for htcpDataHeader->RR */enum { RR_REQUEST, RR_RESPONSE};static u_num32 msg_id_counter = 0;static int htcpInSocket = -1;static int htcpOutSocket = -1;#define N_QUERIED_KEYS 256static cache_key queried_keys[N_QUERIED_KEYS][MD5_DIGEST_CHARS];static char *htcpBuildPacket(htcpStuff * stuff, ssize_t * len);static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz);static htcpDetail *htcpUnpackDetail(char *buf, int sz);static int htcpUnpackCountstr(char *buf, int sz, char **str);static ssize_t htcpBuildAuth(char *buf, size_t buflen);static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s);static ssize_t htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff);static ssize_t htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff);static ssize_t htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff);static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff);static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff);static void htcpFreeSpecifier(htcpSpecifier * s);static void htcpFreeDetail(htcpDetail * s);static void htcpHandle(char *buf, int sz, struct sockaddr_in *from);static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from);static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);static void htcpRecv(int fd, void *data);static void htcpSend(const char *buf, int len, struct sockaddr_in *to);static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *);static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *);static voidhtcpHexdump(const char *tag, const char *s, int sz){#if USE_HEXDUMP int i; int k; char hex[80]; debug(31, 3) ("htcpHexdump %s\n", tag); memset(hex, '\0', 80); for (i = 0; i < sz; i++) { k = i % 16; snprintf(&hex[k * 3], 4, " %02x", (int) *(s + i)); if (k < 15 && i < (sz - 1)) continue; debug(31, 3) ("\t%s\n", hex); memset(hex, '\0', 80); }#endif}/* * STUFF FOR SENDING HTCP MESSAGES */static ssize_thtcpBuildAuth(char *buf, size_t buflen){ htcpAuthHeader auth; size_t copy_sz = 0; assert(2 == sizeof(u_short)); auth.length = htons(2); copy_sz += 2; assert(buflen >= copy_sz); xmemcpy(buf, &auth, copy_sz); return copy_sz;}static ssize_thtcpBuildCountstr(char *buf, size_t buflen, const char *s){ u_short length; size_t len; off_t off = 0; if (buflen - off < 2) return -1; if (s) len = strlen(s); else len = 0; debug(31, 3) ("htcpBuildCountstr: LENGTH = %d\n", len); debug(31, 3) ("htcpBuildCountstr: TEXT = {%s}\n", s ? s : "<NULL>"); length = htons((u_short) len); xmemcpy(buf + off, &length, 2); off += 2; if (buflen - off < len) return -1; if (len) xmemcpy(buf + off, s, len); off += len; return off;}static ssize_thtcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff){ ssize_t off = 0; ssize_t s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.method); if (s < 0) return s; off += s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.uri); if (s < 0) return s; off += s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.version); if (s < 0) return s; off += s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.req_hdrs); if (s < 0) return s; off += s; debug(31, 3) ("htcpBuildSpecifier: size %d\n", (int) off); return off;}static ssize_thtcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff){ ssize_t off = 0; ssize_t s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.resp_hdrs); if (s < 0) return s; off += s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.entity_hdrs); if (s < 0) return s; off += s; s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.cache_hdrs); if (s < 0) return s; off += s; return off;}static ssize_thtcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff){ switch (stuff->rr) { case RR_REQUEST: debug(31, 3) ("htcpBuildTstOpData: RR_REQUEST\n"); return htcpBuildSpecifier(buf, buflen, stuff); case RR_RESPONSE: debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSE\n"); debug(31, 3) ("htcpBuildTstOpData: F1 = %d\n", stuff->f1); if (stuff->f1) /* cache miss */ return 0; else /* cache hit */ return htcpBuildDetail(buf, buflen, stuff); default: fatal_dump("htcpBuildTstOpData: bad RR value"); } return 0;}static ssize_thtcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff){ ssize_t off = 0; debug(31, 3) ("htcpBuildOpData: opcode %s\n", htcpOpcodeStr[stuff->op]); switch (stuff->op) { case HTCP_TST: off = htcpBuildTstOpData(buf + off, buflen, stuff); break; default: assert(0); break; } return off;}static ssize_thtcpBuildData(char *buf, size_t buflen, htcpStuff * stuff){ ssize_t off = 0; ssize_t op_data_sz; size_t hdr_sz = sizeof(htcpDataHeader); htcpDataHeader hdr; if (buflen < hdr_sz) return -1; off += hdr_sz; /* skip! */ op_data_sz = htcpBuildOpData(buf + off, buflen - off, stuff); if (op_data_sz < 0) return op_data_sz; off += op_data_sz; debug(31, 3) ("htcpBuildData: hdr.length = %d\n", (int) off); hdr.length = (u_short) off; hdr.opcode = stuff->op; hdr.response = stuff->response; hdr.RR = stuff->rr; hdr.F1 = stuff->f1; hdr.msg_id = stuff->msg_id; /* convert multi-byte fields */ hdr.length = htons(hdr.length); hdr.msg_id = htonl(hdr.msg_id); xmemcpy(buf, &hdr, hdr_sz); debug(31, 3) ("htcpBuildData: size %d\n", (int) off); return off;}static char *htcpBuildPacket(htcpStuff * stuff, ssize_t * len){ size_t buflen = 8192; size_t s; ssize_t off = 0; size_t hdr_sz = sizeof(htcpHeader); htcpHeader hdr; char *buf = xcalloc(buflen, 1); /* skip the header -- we don't know the overall length */ if (buflen < hdr_sz) return NULL; off += hdr_sz; s = htcpBuildData(buf + off, buflen - off, stuff); if (s < 0) return NULL; off += s; s = htcpBuildAuth(buf + off, buflen - off); if (s < 0) return NULL; off += s; hdr.length = htons((u_short) off); hdr.major = 0; hdr.minor = 0; xmemcpy(buf, &hdr, hdr_sz); *len = off; debug(31, 3) ("htcpBuildPacket: size %d\n", (int) off); return buf;}static voidhtcpSend(const char *buf, int len, struct sockaddr_in *to){ int x; debug(31, 3) ("htcpSend: %s/%d\n", inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port)); htcpHexdump("htcpSend", buf, len); x = comm_udp_sendto(htcpOutSocket, to, sizeof(struct sockaddr_in), buf, len); if (x < 0) debug(31, 0) ("htcpSend: FD %d sendto: %s\n", htcpOutSocket, xstrerror());}/* * STUFF FOR RECEIVING HTCP MESSAGES */static voidhtcpFreeSpecifier(htcpSpecifier * s){ safe_free(s->method); safe_free(s->uri); safe_free(s->version); safe_free(s->req_hdrs); xfree(s);}static voidhtcpFreeDetail(htcpDetail * d){ safe_free(d->resp_hdrs); safe_free(d->entity_hdrs); safe_free(d->cache_hdrs); xfree(d);}static inthtcpUnpackCountstr(char *buf, int sz, char **str){ u_short l; debug(31, 3) ("htcpUnpackCountstr: sz = %d\n", sz); if (sz < 2) { debug(31, 3) ("htcpUnpackCountstr: sz < 2\n"); return -1; } htcpHexdump("htcpUnpackCountstr", buf, sz); xmemcpy(&l, buf, 2); l = ntohs(l); buf += 2; sz -= 2; debug(31, 3) ("htcpUnpackCountstr: LENGTH = %d\n", (int) l); if (sz < l) { debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz, l); return -1; } if (str) { *str = xmalloc(l + 1); xstrncpy(*str, buf, l + 1); debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str); } return (int) l + 2;}static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz){ htcpSpecifier *s = xcalloc(1, sizeof(htcpSpecifier)); int o; debug(31, 3) ("htcpUnpackSpecifier: %d bytes\n", (int) sz); o = htcpUnpackCountstr(buf, sz, &s->method); if (o < 0) { debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -