⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpreply.c

📁 -
💻 C
字号:
/* * $Id: HttpReply.c,v 1.35.2.1 1999/04/19 00:43:00 wessels Exp $ * * DEBUG: section 58    HTTP Reply (Response) * AUTHOR: Alex Rousskov * * 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"/* local constants *//* these entity-headers must be ignored if a bogus server sends them in 304 */static HttpHeaderMask Denied304HeadersMask;static http_hdr_type Denied304HeadersArr[] ={    HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH,    HDR_CONTENT_LOCATION, HDR_CONTENT_RANGE, HDR_LAST_MODIFIED, HDR_LINK,    HDR_OTHER};/* local routines */static void httpReplyInit(HttpReply * rep);static void httpReplyClean(HttpReply * rep);static void httpReplyDoDestroy(HttpReply * rep);static void httpReplyHdrCacheInit(HttpReply * rep);static void httpReplyHdrCacheClean(HttpReply * rep);static int httpReplyParseStep(HttpReply * rep, const char *parse_start, int atEnd);static int httpReplyParseError(HttpReply * rep);static int httpReplyIsolateStart(const char **parse_start, const char **blk_start, const char **blk_end);/* module initialization */voidhttpReplyInitModule(){    httpHeaderMaskInit(&Denied304HeadersMask, 0);    httpHeaderCalcMask(&Denied304HeadersMask, (const int *) Denied304HeadersArr, countof(Denied304HeadersArr));}HttpReply *httpReplyCreate(){    HttpReply *rep = memAllocate(MEM_HTTP_REPLY);    debug(58, 7) ("creating rep: %p\n", rep);    httpReplyInit(rep);    return rep;}static voidhttpReplyInit(HttpReply * rep){    assert(rep);    rep->hdr_sz = 0;    rep->pstate = psReadyToParseStartLine;    httpBodyInit(&rep->body);    httpHeaderInit(&rep->header, hoReply);    httpReplyHdrCacheInit(rep);    httpStatusLineInit(&rep->sline);}static voidhttpReplyClean(HttpReply * rep){    assert(rep);    httpBodyClean(&rep->body);    httpReplyHdrCacheClean(rep);    httpHeaderClean(&rep->header);    httpStatusLineClean(&rep->sline);}voidhttpReplyDestroy(HttpReply * rep){    assert(rep);    debug(58, 7) ("destroying rep: %p\n", rep);    httpReplyClean(rep);    httpReplyDoDestroy(rep);}voidhttpReplyReset(HttpReply * rep){    httpReplyClean(rep);    httpReplyInit(rep);}/* absorb: copy the contents of a new reply to the old one, destroy new one */voidhttpReplyAbsorb(HttpReply * rep, HttpReply * new_rep){    assert(rep && new_rep);    httpReplyClean(rep);    *rep = *new_rep;    /* cannot use Clean() on new reply now! */    httpReplyDoDestroy(new_rep);}/* parses a 4K buffer that may not be 0-terminated; returns true on success */inthttpReplyParse(HttpReply * rep, const char *buf){    /*     * this extra buffer/copy will be eliminated when headers become meta-data     * in store. Currently we have to xstrncpy the buffer becuase store.c may     * feed a non 0-terminated buffer to us.     */    char *headers = memAllocate(MEM_4K_BUF);    int success;    /* reset current state, because we are not used in incremental fashion */    httpReplyReset(rep);    /* put a 0-terminator */    xstrncpy(headers, buf, 4096);    success = httpReplyParseStep(rep, headers, 0);    memFree(headers, MEM_4K_BUF);    return success == 1;}voidhttpReplyPackInto(const HttpReply * rep, Packer * p){    assert(rep);    httpStatusLinePackInto(&rep->sline, p);    httpHeaderPackInto(&rep->header, p);    packerAppend(p, "\r\n", 2);    httpBodyPackInto(&rep->body, p);}/* create memBuf, create mem-based packer,  pack, destroy packer, return MemBuf */MemBufhttpReplyPack(const HttpReply * rep){    MemBuf mb;    Packer p;    assert(rep);    memBufDefInit(&mb);    packerToMemInit(&p, &mb);    httpReplyPackInto(rep, &p);    packerClean(&p);    return mb;}/* swap: create swap-based packer, pack, destroy packer */voidhttpReplySwapOut(const HttpReply * rep, StoreEntry * e){    Packer p;    assert(rep && e);    packerToStoreInit(&p, e);    httpReplyPackInto(rep, &p);    packerClean(&p);}MemBufhttpPackedReply(double ver, http_status status, const char *ctype,    int clen, time_t lmt, time_t expires){    HttpReply *rep = httpReplyCreate();    MemBuf mb;    httpReplySetHeaders(rep, ver, status, ctype, NULL, clen, lmt, expires);    mb = httpReplyPack(rep);    httpReplyDestroy(rep);    return mb;}MemBufhttpPacked304Reply(const HttpReply * rep){    static const http_hdr_type ImsEntries[] =    {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER};    int t;    MemBuf mb;    Packer p;    HttpHeaderEntry *e;    assert(rep);    memBufDefInit(&mb);    packerToMemInit(&p, &mb);    memBufPrintf(&mb, "%s", "HTTP/1.0 304 Not Modified\r\n");    for (t = 0; ImsEntries[t] != HDR_OTHER; ++t)	if ((e = httpHeaderFindEntry(&rep->header, ImsEntries[t])))	    httpHeaderEntryPackInto(e, &p);    memBufAppend(&mb, "\r\n", 2);    packerClean(&p);    return mb;}voidhttpReplySetHeaders(HttpReply * reply, double ver, http_status status, const char *reason,    const char *ctype, int clen, time_t lmt, time_t expires){    HttpHeader *hdr;    assert(reply);    httpStatusLineSet(&reply->sline, ver, status, reason);    hdr = &reply->header;    httpHeaderPutStr(hdr, HDR_SERVER, full_appname_string);    httpHeaderPutStr(hdr, HDR_MIME_VERSION, "1.0");    httpHeaderPutTime(hdr, HDR_DATE, squid_curtime);    if (ctype) {	httpHeaderPutStr(hdr, HDR_CONTENT_TYPE, ctype);	stringInit(&reply->content_type, ctype);    } else	reply->content_type = StringNull;    if (clen >= 0)	httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, clen);    if (expires >= 0)	httpHeaderPutTime(hdr, HDR_EXPIRES, expires);    if (lmt > 0)		/* this used to be lmt != 0 @?@ */	httpHeaderPutTime(hdr, HDR_LAST_MODIFIED, lmt);    reply->date = squid_curtime;    reply->content_length = clen;    reply->expires = expires;    reply->last_modified = lmt;}voidhttpRedirectReply(HttpReply * reply, http_status status, const char *loc){    HttpHeader *hdr;    assert(reply);    httpStatusLineSet(&reply->sline, 1.0, status, httpStatusString(status));    hdr = &reply->header;    httpHeaderPutStr(hdr, HDR_SERVER, full_appname_string);    httpHeaderPutTime(hdr, HDR_DATE, squid_curtime);    httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, 0);    httpHeaderPutStr(hdr, HDR_LOCATION, loc);    reply->date = squid_curtime;    reply->content_length = 0;}voidhttpReplyUpdateOnNotModified(HttpReply * rep, HttpReply * freshRep){    assert(rep && freshRep);    /* clean cache */    httpReplyHdrCacheClean(rep);    /* update raw headers */    httpHeaderUpdate(&rep->header, &freshRep->header,	(const HttpHeaderMask *) &Denied304HeadersMask);    /* init cache */    httpReplyHdrCacheInit(rep);}/* internal routines *//* internal function used by Destroy and Absorb */static voidhttpReplyDoDestroy(HttpReply * rep){    memFree(rep, MEM_HTTP_REPLY);}/* sync this routine when you update HttpReply struct */static voidhttpReplyHdrCacheInit(HttpReply * rep){    const HttpHeader *hdr = &rep->header;    const char *str;    rep->content_length = httpHeaderGetInt(hdr, HDR_CONTENT_LENGTH);    rep->date = httpHeaderGetTime(hdr, HDR_DATE);    rep->last_modified = httpHeaderGetTime(hdr, HDR_LAST_MODIFIED);    rep->expires = httpHeaderGetTime(hdr, HDR_EXPIRES);    str = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE);    if (str)	stringLimitInit(&rep->content_type, str, strcspn(str, ";\t "));    else	rep->content_type = StringNull;    rep->cache_control = httpHeaderGetCc(hdr);    rep->content_range = httpHeaderGetContRange(hdr);    rep->keep_alive = httpMsgIsPersistent(rep->sline.version, &rep->header);    /* final adjustments */    /* The max-age directive takes priority over Expires, check it first */    if (rep->cache_control && rep->cache_control->max_age >= 0)	rep->expires = squid_curtime + rep->cache_control->max_age;    else	/*	 * The HTTP/1.0 specs says that robust implementations should consider bad	 * or malformed Expires header as equivalent to "expires immediately."	 */    if (rep->expires < 0 && httpHeaderHas(hdr, HDR_EXPIRES))	rep->expires = squid_curtime;}/* sync this routine when you update HttpReply struct */static voidhttpReplyHdrCacheClean(HttpReply * rep){    stringClean(&rep->content_type);    if (rep->cache_control)	httpHdrCcDestroy(rep->cache_control);    if (rep->content_range)	httpHdrContRangeDestroy(rep->content_range);}/* * parses a 0-terminating buffer into HttpReply.  * Returns: *      +1 -- success  *       0 -- need more data (partial parse) *      -1 -- parse error */static inthttpReplyParseStep(HttpReply * rep, const char *buf, int atEnd){    const char *parse_start = buf;    const char *blk_start, *blk_end;    const char **parse_end_ptr = &blk_end;    assert(rep);    assert(parse_start);    assert(rep->pstate < psParsed);    *parse_end_ptr = parse_start;    if (rep->pstate == psReadyToParseStartLine) {	if (!httpReplyIsolateStart(&parse_start, &blk_start, &blk_end))	    return 0;	if (!httpStatusLineParse(&rep->sline, blk_start, blk_end))	    return httpReplyParseError(rep);	*parse_end_ptr = parse_start;	rep->hdr_sz = *parse_end_ptr - buf;	rep->pstate++;    }    if (rep->pstate == psReadyToParseHeaders) {	if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) {	    if (atEnd)		blk_start = parse_start, blk_end = blk_start + strlen(blk_start);	    else		return 0;	}	if (!httpHeaderParse(&rep->header, blk_start, blk_end))	    return httpReplyParseError(rep);	httpReplyHdrCacheInit(rep);	*parse_end_ptr = parse_start;	rep->hdr_sz = *parse_end_ptr - buf;	rep->pstate++;    }    return 1;}/* handy: resets and returns -1 */static inthttpReplyParseError(HttpReply * rep){    assert(rep);    /* reset */    httpReplyReset(rep);    /* indicate an error */    rep->sline.status = HTTP_INVALID_HEADER;    return -1;}/* find first CRLF */static inthttpReplyIsolateStart(const char **parse_start, const char **blk_start, const char **blk_end){    int slen = strcspn(*parse_start, "\r\n");    if (!(*parse_start)[slen])	/* no CRLF found */	return 0;    *blk_start = *parse_start;    *blk_end = *blk_start + slen;    while (**blk_end == '\r')	/* CR */	(*blk_end)++;    if (**blk_end == '\n')	/* LF */	(*blk_end)++;    *parse_start = *blk_end;    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -