📄 htcp.c
字号:
htcpFreeSpecifier(s); return NULL; } buf += o; sz -= o; o = htcpUnpackCountstr(buf, sz, &s->uri); if (o < 0) { debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n"); htcpFreeSpecifier(s); return NULL; } buf += o; sz -= o; o = htcpUnpackCountstr(buf, sz, &s->version); if (o < 0) { debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n"); htcpFreeSpecifier(s); return NULL; } buf += o; sz -= o; o = htcpUnpackCountstr(buf, sz, &s->req_hdrs); if (o < 0) { debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n"); htcpFreeSpecifier(s); return NULL; } buf += o; sz -= o; debug(31, 3) ("htcpUnpackSpecifier: %d bytes left\n", sz); return s;}static htcpDetail *htcpUnpackDetail(char *buf, int sz){ htcpDetail *d = xcalloc(1, sizeof(htcpDetail)); int o; debug(31, 3) ("htcpUnpackDetail: %d bytes\n", (int) sz); o = htcpUnpackCountstr(buf, sz, &d->resp_hdrs); if (o < 0) { debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n"); htcpFreeDetail(d); return NULL; } buf += o; sz -= o; o = htcpUnpackCountstr(buf, sz, &d->entity_hdrs); if (o < 0) { debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n"); htcpFreeDetail(d); return NULL; } buf += o; sz -= o; o = htcpUnpackCountstr(buf, sz, &d->cache_hdrs); if (o < 0) { debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n"); htcpFreeDetail(d); return NULL; } buf += o; sz -= o; debug(31, 3) ("htcpUnpackDetail: %d bytes left\n", sz); return d;}static voidhtcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from){ htcpStuff stuff; char *pkt; HttpHeader hdr; MemBuf mb; Packer p; ssize_t pktlen; char *host; int rtt = 0; int hops = 0; int samp = 0; char cto_buf[128]; stuff.op = HTCP_TST; stuff.rr = RR_RESPONSE; stuff.f1 = 0; stuff.response = e ? 0 : 1; stuff.msg_id = dhdr->msg_id; if (spec) { memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHeaderInit(&hdr, hoHtcpReply); stuff.S.method = spec->method; stuff.S.uri = spec->uri; stuff.S.version = spec->version; stuff.S.req_hdrs = spec->req_hdrs; httpHeaderPutInt(&hdr, HDR_AGE, e->timestamp <= squid_curtime ? squid_curtime - e->timestamp : 0); httpHeaderPackInto(&hdr, &p); stuff.D.resp_hdrs = xstrdup(mb.buf); debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}\n", stuff.D.resp_hdrs); memBufReset(&mb); httpHeaderReset(&hdr); if (e->expires > -1) httpHeaderPutTime(&hdr, HDR_EXPIRES, e->expires); if (e->lastmod > -1) httpHeaderPutTime(&hdr, HDR_LAST_MODIFIED, e->lastmod); httpHeaderPackInto(&hdr, &p); stuff.D.entity_hdrs = xstrdup(mb.buf); debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}\n", stuff.D.entity_hdrs); memBufReset(&mb); httpHeaderReset(&hdr); if ((host = urlHostname(spec->uri))) { netdbHostData(host, &samp, &rtt, &hops); if (rtt || hops) { snprintf(cto_buf, 128, "%s %d %f %d", host, samp, 0.001 * rtt, hops); httpHeaderPutExt(&hdr, "Cache-to-Origin", cto_buf); } } httpHeaderPackInto(&hdr, &p); stuff.D.cache_hdrs = xstrdup(mb.buf); debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}\n", stuff.D.cache_hdrs); memBufClean(&mb); httpHeaderClean(&hdr); packerClean(&p); } pkt = htcpBuildPacket(&stuff, &pktlen); if (pkt == NULL) { debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n"); return; } htcpSend(pkt, (int) pktlen, from); xfree(pkt);}static voidhtcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from){ debug(31, 3) ("htcpHandleNop: Unimplemented\n");}static voidhtcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from){ debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz); if (hdr->RR == RR_REQUEST) htcpHandleTstRequest(hdr, buf, sz, from); else htcpHandleTstResponse(hdr, buf, sz, from);}static voidhtcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from){ htcpReplyData htcpReply; cache_key *key = NULL; htcpDetail *d = NULL; char *t; if (hdr->F1 == 1) { debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n"); return; } memset(&htcpReply, '\0', sizeof(htcpReply)); httpHeaderInit(&htcpReply.hdr, hoHtcpReply); htcpReply.msg_id = hdr->msg_id; debug(31, 3) ("htcpHandleTstResponse: msg_id = %d\n", (int) htcpReply.msg_id); htcpReply.hit = hdr->response ? 0 : 1; if (hdr->F1) { debug(31, 3) ("htcpHandleTstResponse: MISS\n"); } else { debug(31, 3) ("htcpHandleTstResponse: HIT\n"); d = htcpUnpackDetail(buf, sz); if (d == NULL) { debug(31, 1) ("htcpHandleTstResponse: bad DETAIL\n"); return; } if ((t = d->resp_hdrs)) httpHeaderParse(&htcpReply.hdr, t, t + strlen(t)); if ((t = d->entity_hdrs)) httpHeaderParse(&htcpReply.hdr, t, t + strlen(t)); if ((t = d->cache_hdrs)) httpHeaderParse(&htcpReply.hdr, t, t + strlen(t)); } key = queried_keys[htcpReply.msg_id % N_QUERIED_KEYS]; debug(31, 3) ("htcpHandleTstResponse: key (%p) %s\n", key, storeKeyText(key)); neighborsHtcpReply(key, &htcpReply, from); if (d) htcpFreeDetail(d);}static voidhtcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from){ /* buf should be a SPECIFIER */ htcpSpecifier *s; StoreEntry *e; method_t m; if (sz == 0) { debug(31, 3) ("htcpHandleTst: nothing to do\n"); return; } if (dhdr->F1 == 0) return; s = htcpUnpackSpecifier(buf, sz); if (NULL == s) { debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n"); return; } debug(31, 3) ("htcpHandleTstRequest: %s %s %s\n", s->method, s->uri, s->version); m = urlParseMethod(s->method); debug(31, 3) ("htcpHandleTstRequest: %s\n", s->req_hdrs); e = storeGetPublic(s->uri, m); if (NULL == e) { /* cache miss */ htcpTstReply(dhdr, NULL, NULL, from);#if WIP } else if (!checkHeaders()) { /* refresh/other miss */ htcpTstReply(dhdr, NULL, NULL, from);#endif } else { /* hit */ htcpTstReply(dhdr, e, s, from); } htcpFreeSpecifier(s);}static voidhtcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from){ debug(31, 3) ("htcpHandleMon: Unimplemented\n");}static voidhtcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from){ debug(31, 3) ("htcpHandleSet: Unimplemented\n");}static voidhtcpHandleData(char *buf, int sz, struct sockaddr_in *from){ htcpDataHeader hdr; if (sz < sizeof(htcpDataHeader)) { debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader size\n"); return; } xmemcpy(&hdr, buf, sizeof(htcpDataHeader)); hdr.length = ntohs(hdr.length); hdr.msg_id = ntohl(hdr.msg_id); debug(31, 3) ("htcpHandleData: sz = %d\n", sz); debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr.length); if (hdr.opcode > HTCP_END) { debug(31, 0) ("htcpHandleData: opcode %d out of range\n", (int) hdr.opcode); return; } debug(31, 3) ("htcpHandleData: opcode = %d %s\n", (int) hdr.opcode, htcpOpcodeStr[hdr.opcode]); debug(31, 3) ("htcpHandleData: response = %d\n", (int) hdr.response); debug(31, 3) ("htcpHandleData: F1 = %d\n", (int) hdr.F1); debug(31, 3) ("htcpHandleData: RR = %d\n", (int) hdr.RR); debug(31, 3) ("htcpHandleData: msg_id = %d\n", (int) hdr.msg_id); if (sz < hdr.length) { debug(31, 0) ("htcpHandle: sz < hdr.length\n"); return; } /* * set sz = hdr.length so we ignore any AUTH fields following * the DATA. */ sz = (int) hdr.length; buf += sizeof(htcpDataHeader); sz -= sizeof(htcpDataHeader); debug(31, 3) ("htcpHandleData: sz = %d\n", sz); htcpHexdump("htcpHandleData", buf, sz); switch (hdr.opcode) { case HTCP_NOP: htcpHandleNop(&hdr, buf, sz, from); break; case HTCP_TST: htcpHandleTst(&hdr, buf, sz, from); break; case HTCP_MON: htcpHandleMon(&hdr, buf, sz, from); break; case HTCP_SET: htcpHandleSet(&hdr, buf, sz, from); break; default: assert(0); break; }}static voidhtcpHandle(char *buf, int sz, struct sockaddr_in *from){ htcpHeader htcpHdr; if (sz < sizeof(htcpHeader)) { debug(31, 0) ("htcpHandle: msg size less than htcpHeader size\n"); return; } htcpHexdump("htcpHandle", buf, sz); xmemcpy(&htcpHdr, buf, sizeof(htcpHeader)); htcpHdr.length = ntohs(htcpHdr.length); debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr.length); debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr.major); debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr.minor); if (sz != htcpHdr.length) { debug(31, 0) ("htcpHandle: sz != htcpHdr.length\n"); return; } buf += sizeof(htcpHeader); sz -= sizeof(htcpHeader); htcpHandleData(buf, sz, from);}static voidhtcpRecv(int fd, void *data){ static char buf[8192]; int len; static struct sockaddr_in from; int flen = sizeof(struct sockaddr_in); memset(&from, '\0', flen); Counter.syscalls.sock.recvfroms++; len = recvfrom(fd, buf, 8192, 0, (struct sockaddr *) &from, &flen); debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n", fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port)); htcpHandle(buf, len, &from); commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);}/* * ====================================================================== * PUBLIC FUNCTIONS * ====================================================================== */voidhtcpInit(void){ enter_suid(); htcpInSocket = comm_open(SOCK_DGRAM, 0, Config.Addrs.udp_incoming, Config.Port.htcp, COMM_NONBLOCKING, "HTCP Socket"); leave_suid(); if (htcpInSocket < 0) fatal("Cannot open HTCP Socket"); commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0); debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.\n", (int) Config.Port.htcp, htcpInSocket); if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) { enter_suid(); htcpOutSocket = comm_open(SOCK_DGRAM, 0, Config.Addrs.udp_outgoing, Config.Port.htcp, COMM_NONBLOCKING, "Outgoing HTCP Socket"); leave_suid(); if (htcpOutSocket < 0) fatal("Cannot open Outgoing HTCP Socket"); commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0); debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.\n", (int) Config.Port.htcp, htcpOutSocket); fd_note(htcpInSocket, "Incoming HTCP socket"); } else { htcpOutSocket = htcpInSocket; }}voidhtcpQuery(StoreEntry * e, request_t * req, peer * p){ cache_key *save_key; char *pkt; ssize_t pktlen; char vbuf[32]; htcpStuff stuff; HttpHeader hdr; Packer pa; MemBuf mb; http_state_flags flags; memset(&flags, '\0', sizeof(flags)); snprintf(vbuf, sizeof(vbuf), "%3.1f", req->http_ver); stuff.op = HTCP_TST; stuff.rr = RR_REQUEST; stuff.f1 = 1; stuff.response = 0; stuff.msg_id = ++msg_id_counter; stuff.S.method = (char *) RequestMethodStr[req->method]; stuff.S.uri = (char *) storeUrl(e); stuff.S.version = vbuf; httpBuildRequestHeader(req, req, e, &hdr, -1, flags); memBufDefInit(&mb); packerToMemInit(&pa, &mb); httpHeaderPackInto(&hdr, &pa); httpHeaderClean(&hdr); packerClean(&pa); stuff.S.req_hdrs = mb.buf; pkt = htcpBuildPacket(&stuff, &pktlen); if (pkt == NULL) { debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n"); return; } htcpSend(pkt, (int) pktlen, &p->in_addr); save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS]; storeKeyCopy(save_key, e->key); debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key, storeKeyText(save_key)); xfree(pkt);}/* * htcpSocketShutdown only closes the 'in' socket if it is * different than the 'out' socket. */voidhtcpSocketShutdown(void){ if (htcpInSocket < 0) return; if (htcpInSocket != htcpOutSocket) { debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket); comm_close(htcpInSocket); } /* * Here we set 'htcpInSocket' to -1 even though the HTCP 'in' * and 'out' sockets might be just one FD. This prevents this * function from executing repeatedly. When we are really ready to * exit or restart, main will comm_close the 'out' descriptor. */ htcpInSocket = -1; /* * Normally we only write to the outgoing HTCP socket, but * we also have a read handler there to catch messages sent * to that specific interface. During shutdown, we must * disable reading on the outgoing socket. */ assert(htcpOutSocket > -1); commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);}voidhtcpSocketClose(void){ htcpSocketShutdown(); if (htcpOutSocket > -1) { debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket); comm_close(htcpOutSocket); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -