HTConLen.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:6k
- /* HTConlen.c
- ** CONTENT LENGTH COUNTER STREAM
- **
- ** (c) COPYRIGHT MIT 1995.
- ** Please first read the full copyright statement in the file COPYRIGH.
- **
- ** This stream counts the number of bytes in a stream until it reaches
- ** max number of bytes it can occupy. If this happens then it gives up.
- */
- /* Library include files */
- #include "tcp.h"
- #include "HTUtils.h"
- #include "HTString.h"
- #include "HTReq.h"
- #include "HTConLen.h" /* Implemented here */
- #define HT_MIN_BLOCK 0x100
- #define HT_MAX_BLOCK 0x2000
- #define HT_MAX_SIZE 0x10000
- #define PUTBLOCK(b, l) (*me->target->isa->put_block) (me->target, b, l)
- typedef struct _HTBufItem {
- int len;
- char * buf;
- struct _HTBufItem * next;
- } HTBufItem;
- struct _HTStream {
- HTStreamClass * isa;
- HTRequest * request;
- HTStream * target;
- char * tmp_buf;
- int tmp_ind;
- int tmp_max;
- HTBufItem * head;
- HTBufItem * tail;
- int max_size;
- int cur_size;
- int conlen;
- BOOL ignore;
- BOOL give_up;
- };
- /* ------------------------------------------------------------------------- */
- /*
- ** MIME output with content-length calculation
- ** -------------------------------------------
- ** This stream also buffers the result to find out the content length.
- ** If a maximum buffer limit is reached Content-Length is calculated
- ** for logs but it is not sent to the client -- rather the buffer is
- ** flushed right away.
- ** Code taken from HTRequest.c written by Ari Luotonen and modified to
- ** fit new stream model
- */
- PRIVATE BOOL free_buf (HTBufItem * me)
- {
- if (me) {
- HT_FREE(me->buf);
- HT_FREE(me);
- return YES;
- }
- return NO;
- }
- PRIVATE void free_buf_all (HTStream * me)
- {
- HTBufItem * cur = me->head;
- HTBufItem * killme;
- me->tmp_ind = 0;
- me->tmp_max = 0;
- HT_FREE(me->tmp_buf);
- while (cur) {
- killme = cur;
- cur = cur->next;
- free_buf(cur);
- }
- me->head = me->tail = NULL;
- }
- PRIVATE void append_buf (HTStream * me)
- {
- HTBufItem * b;
- if ((b = (HTBufItem *) HT_CALLOC(1, sizeof(HTBufItem))) == NULL)
- HT_OUTOFMEM("append_buf");
- b->len = me->tmp_ind;
- b->buf = me->tmp_buf;
- me->tmp_ind = 0;
- me->tmp_max = 0;
- me->tmp_buf = 0;
- if (me->tail)
- me->tail->next = b;
- else
- me->head = b;
- me->tail = b;
- }
- PRIVATE BOOL alloc_new (HTStream * me, int size)
- {
- if (me->conlen >= me->max_size) {
- if (STREAM_TRACE)
- TTYPrint(TDEST,"StreamBuffer size %d reached, going transparentn",
- me->max_size);
- return NO;
- } else if (size) {
- me->tmp_ind = 0;
- me->tmp_max = size;
- if ((me->tmp_buf = (char *) HT_MALLOC(size)) == NULL)
- HT_OUTOFMEM("buf_put_char");
- if (STREAM_TRACE)
- TTYPrint(TDEST, "StreamBuffer created with len %dn", size);
- return YES;
- }
- return NO;
- }
- PRIVATE int buf_flush (HTStream * me)
- {
- HTBufItem * cur;
- if (me->tmp_buf) append_buf(me);
- while ((cur = me->head)) {
- int status;
- if ((status = PUTBLOCK(cur->buf, cur->len)) != HT_OK) return status;
- me->head = cur->next;
- free_buf(cur);
- }
- me->give_up = YES;
- return HT_OK;
- }
- PRIVATE int buf_put_block (HTStream * me, CONST char * b, int l)
- {
- me->conlen += l;
- if (!me->give_up) {
- if (me->tmp_buf && me->tmp_max-me->tmp_ind >= l) { /* Still room */
- memcpy(me->tmp_buf + me->tmp_ind, b, l);
- me->tmp_ind += l;
- return HT_OK;
- } else {
- if (me->tmp_buf) append_buf(me);
- if (me->cur_size < HT_MAX_BLOCK) {
- int newsize = me->cur_size ? me->cur_size : HT_MIN_BLOCK;
- while (l > newsize && newsize < HT_MAX_BLOCK) newsize *= 2;
- me->cur_size = newsize;
- }
- if (!alloc_new(me, me->cur_size)) {
- int status = buf_flush(me);
- if (status != HT_OK) return status;
- me->give_up = YES;
- } else {
- memcpy(me->tmp_buf, b, l);
- me->tmp_ind = l;
- }
- }
- }
- if (me->give_up) return PUTBLOCK(b, l);
- return HT_OK;
- }
- PRIVATE int buf_put_char (HTStream * me, char c)
- {
- return buf_put_block(me, &c, 1);
- }
- PRIVATE int buf_put_string (HTStream * me, CONST char * s)
- {
- return buf_put_block(me, s, (int) strlen(s));
- }
- PRIVATE int buf_free (HTStream * me)
- {
- int status = HT_OK;
- if (!me->ignore) {
- HTParentAnchor *anchor = HTRequest_anchor(me->request);
- if (STREAM_TRACE)
- TTYPrint(TDEST,"nCalculated.. content-length: %dn", me->conlen);
- HTAnchor_setLength(anchor, me->conlen);
- }
- if (!me->give_up && (status = buf_flush(me)) != HT_OK)
- return status;
- if ((status = (*me->target->isa->_free)(me->target)) != HT_OK)
- return status;
- HT_FREE(me);
- return status;
- }
- PRIVATE int buf_abort (HTStream * me, HTList * e)
- {
- if (me->target) (*me->target->isa->abort)(me->target,e);
- free_buf_all(me);
- HT_FREE(me);
- if (PROT_TRACE) TTYPrint(TDEST, "Length...... ABORTING...n");
- return HT_ERROR;
- }
- HTStreamClass HTContentCounterClass = {
- "ContentCounter",
- buf_flush,
- buf_free,
- buf_abort,
- buf_put_char,
- buf_put_string,
- buf_put_block
- };
- PUBLIC HTStream * HTContentCounter (HTStream * target,
- HTRequest * request,
- int max_size)
- {
- HTStream * me;
- if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
- HT_OUTOFMEM("HTContentCounter");
- me->isa = &HTContentCounterClass;
- me->target = target;
- me->request = request;
- me->max_size = (max_size > 0) ? max_size : HT_MAX_SIZE;
- if (STREAM_TRACE)
- TTYPrint(TDEST, "Buffer...... Created with size %dn", me->max_size);
- return me;
- }
- PUBLIC HTStream * HTBuffer_new (HTStream * target,
- HTRequest * request,
- int max_size)
- {
- HTStream * me = HTContentCounter(target, request, max_size);
- if (me) me->ignore = YES;
- return me;
- }