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

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: wais.c,v 1.131 1999/01/24 02:26:26 wessels Exp $
  3.  *
  4.  * DEBUG: section 24    WAIS Relay
  5.  * AUTHOR: Harvest Derived
  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 {
  36.     int fd;
  37.     StoreEntry *entry;
  38.     method_t method;
  39.     const HttpHeader *request_hdr;
  40.     char url[MAX_URL];
  41.     request_t *request;
  42.     FwdState *fwd;
  43. } WaisStateData;
  44. static PF waisStateFree;
  45. static PF waisTimeout;
  46. static PF waisReadReply;
  47. static CWCB waisSendComplete;
  48. static PF waisSendRequest;
  49. static void
  50. waisStateFree(int fdnotused, void *data)
  51. {
  52.     WaisStateData *waisState = data;
  53.     if (waisState == NULL)
  54. return;
  55.     storeUnlockObject(waisState->entry);
  56.     requestUnlink(waisState->request);
  57.     cbdataFree(waisState);
  58. }
  59. /* This will be called when socket lifetime is expired. */
  60. static void
  61. waisTimeout(int fd, void *data)
  62. {
  63.     WaisStateData *waisState = data;
  64.     StoreEntry *entry = waisState->entry;
  65.     debug(24, 4) ("waisTimeout: FD %d: '%s'n", fd, storeUrl(entry));
  66.     if (entry->store_status == STORE_PENDING) {
  67. if (entry->mem_obj->inmem_hi == 0) {
  68.     fwdFail(waisState->fwd,
  69. errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
  70. }
  71.     }
  72.     comm_close(fd);
  73. }
  74. /* This will be called when data is ready to be read from fd.  Read until
  75.  * error or connection closed. */
  76. static void
  77. waisReadReply(int fd, void *data)
  78. {
  79.     WaisStateData *waisState = data;
  80.     LOCAL_ARRAY(char, buf, 4096);
  81.     StoreEntry *entry = waisState->entry;
  82.     int len;
  83.     int clen;
  84.     int bin;
  85.     size_t read_sz;
  86. #if DELAY_POOLS
  87.     delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
  88. #endif
  89.     if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
  90. comm_close(fd);
  91. return;
  92.     }
  93.     errno = 0;
  94.     read_sz = 4096;
  95. #if DELAY_POOLS
  96.     read_sz = delayBytesWanted(delay_id, 1, read_sz);
  97. #endif
  98.     Counter.syscalls.sock.reads++;
  99.     len = read(fd, buf, read_sz);
  100.     if (len > 0) {
  101. fd_bytes(fd, len, FD_READ);
  102. #if DELAY_POOLS
  103. delayBytesIn(delay_id, len);
  104. #endif
  105. kb_incr(&Counter.server.all.kbytes_in, len);
  106. kb_incr(&Counter.server.other.kbytes_in, len);
  107.     }
  108.     debug(24, 5) ("waisReadReply: FD %d read len:%dn", fd, len);
  109.     if (len > 0) {
  110. commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
  111. IOStats.Wais.reads++;
  112. for (clen = len - 1, bin = 0; clen; bin++)
  113.     clen >>= 1;
  114. IOStats.Wais.read_hist[bin]++;
  115.     }
  116.     if (len < 0) {
  117. debug(50, 1) ("waisReadReply: FD %d: read failure: %s.n",
  118.     fd, xstrerror());
  119. if (ignoreErrno(errno)) {
  120.     /* reinstall handlers */
  121.     /* XXX This may loop forever */
  122.     commSetSelect(fd, COMM_SELECT_READ,
  123. waisReadReply, waisState, 0);
  124. } else {
  125.     ErrorState *err;
  126.     EBIT_CLR(entry->flags, ENTRY_CACHABLE);
  127.     storeReleaseRequest(entry);
  128.     err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
  129.     err->xerrno = errno;
  130.     err->request = requestLink(waisState->request);
  131.     errorAppendEntry(entry, err);
  132.     comm_close(fd);
  133. }
  134.     } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
  135. ErrorState *err;
  136. err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
  137. err->xerrno = errno;
  138. err->request = requestLink(waisState->request);
  139. errorAppendEntry(entry, err);
  140. comm_close(fd);
  141.     } else if (len == 0) {
  142. /* Connection closed; retrieval done. */
  143. entry->expires = squid_curtime;
  144. fwdComplete(waisState->fwd);
  145. comm_close(fd);
  146.     } else {
  147. storeAppend(entry, buf, len);
  148. commSetSelect(fd,
  149.     COMM_SELECT_READ,
  150.     waisReadReply,
  151.     waisState, 0);
  152.     }
  153. }
  154. /* This will be called when request write is complete. Schedule read of
  155.  * reply. */
  156. static void
  157. waisSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
  158. {
  159.     WaisStateData *waisState = data;
  160.     StoreEntry *entry = waisState->entry;
  161.     debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %dn",
  162. fd, size, errflag);
  163.     if (size > 0) {
  164. fd_bytes(fd, size, FD_WRITE);
  165. kb_incr(&Counter.server.all.kbytes_out, size);
  166. kb_incr(&Counter.server.other.kbytes_out, size);
  167.     }
  168.     if (errflag == COMM_ERR_CLOSING)
  169. return;
  170.     if (errflag) {
  171. ErrorState *err;
  172. err = errorCon(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE);
  173. err->xerrno = errno;
  174. err->request = requestLink(waisState->request);
  175. errorAppendEntry(entry, err);
  176. comm_close(fd);
  177.     } else {
  178. /* Schedule read reply. */
  179. commSetSelect(fd,
  180.     COMM_SELECT_READ,
  181.     waisReadReply,
  182.     waisState, 0);
  183. commSetDefer(fd, fwdCheckDeferRead, entry);
  184.     }
  185. }
  186. /* This will be called when connect completes. Write request. */
  187. static void
  188. waisSendRequest(int fd, void *data)
  189. {
  190.     WaisStateData *waisState = data;
  191.     MemBuf mb;
  192.     const char *Method = RequestMethodStr[waisState->method];
  193.     debug(24, 5) ("waisSendRequest: FD %dn", fd);
  194.     memBufDefInit(&mb);
  195.     memBufPrintf(&mb, "%s %s HTTP/1.0rn", Method, waisState->url);
  196.     if (waisState->request_hdr) {
  197. Packer p;
  198. packerToMemInit(&p, &mb);
  199. httpHeaderPackInto(waisState->request_hdr, &p);
  200. packerClean(&p);
  201.     }
  202.     memBufPrintf(&mb, "rn");
  203.     debug(24, 6) ("waisSendRequest: buf: %sn", mb.buf);
  204.     comm_write_mbuf(fd, mb, waisSendComplete, waisState);
  205.     if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE))
  206. storeSetPublicKey(waisState->entry); /* Make it public */
  207.     EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT);
  208. }
  209. void
  210. waisStart(FwdState * fwd)
  211. {
  212.     WaisStateData *waisState = NULL;
  213.     request_t *request = fwd->request;
  214.     StoreEntry *entry = fwd->entry;
  215.     int fd = fwd->server_fd;
  216.     const char *url = storeUrl(entry);
  217.     method_t method = request->method;
  218.     debug(24, 3) ("waisStart: "%s %s"n", RequestMethodStr[method], url);
  219.     Counter.server.all.requests++;
  220.     Counter.server.other.requests++;
  221.     waisState = xcalloc(1, sizeof(WaisStateData));
  222.     cbdataAdd(waisState, cbdataXfree, 0);
  223.     waisState->method = method;
  224.     waisState->request_hdr = &request->header;
  225.     waisState->fd = fd;
  226.     waisState->entry = entry;
  227.     xstrncpy(waisState->url, url, MAX_URL);
  228.     waisState->request = requestLink(request);
  229.     waisState->fwd = fwd;
  230.     comm_add_close_handler(waisState->fd, waisStateFree, waisState);
  231.     storeLockObject(entry);
  232.     commSetSelect(fd, COMM_SELECT_WRITE, waisSendRequest, waisState, 0);
  233.     commSetTimeout(fd, Config.Timeout.read, waisTimeout, waisState);
  234. }