Annotation of libwww/Library/src/HTConLen.c, revision 2.3

2.1       frystyk     1: /*                                                                  HTConlen.c
                      2: **     CONTENT LENGTH COUNTER STREAM
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **     This stream counts the number of bytes in a stream until it reaches
                      8: **     max number of bytes it can occupy. If this happens then it gives up.
                      9: */
                     10: 
                     11: /* Library include files */
                     12: #include "tcp.h"
                     13: #include "HTUtils.h"
                     14: #include "HTString.h"
                     15: #include "HTReq.h"
                     16: #include "HTConLen.h"                                   /* Implemented here */
                     17: 
                     18: #define HT_MIN_BLOCK   0x200
                     19: #define HT_MAX_BLOCK   0x2000
                     20: #define HT_MAX_SIZE    0x10000
                     21: #define PUTBLOCK(b, l) (*me->target->isa->put_block)        (me->target, b, l)
                     22: 
                     23: typedef struct _HTBufItem {
                     24:     int                        len;
                     25:     char *             buf;
                     26:     struct _HTBufItem *        next;
                     27: } HTBufItem;
                     28: 
                     29: struct _HTStream {
                     30:     HTStreamClass *    isa;
                     31:     HTRequest *                request;
                     32:     HTStream *         target;
                     33: 
                     34:     char *             tmp_buf;
                     35:     int                        tmp_ind;
                     36:     int                        tmp_max;
                     37:     HTBufItem *                head;
                     38:     HTBufItem *                tail;
                     39: 
                     40:     int                        max_size;
                     41:     int                        cur_size;
                     42:     int                        conlen;
                     43: 
                     44:     BOOL               ignore;
                     45:     BOOL               give_up;
                     46: };
                     47: 
                     48: /* ------------------------------------------------------------------------- */
                     49: 
                     50: /*
                     51: **     MIME output with content-length calculation
                     52: **     -------------------------------------------
                     53: **     This stream also buffers the result to find out the content length.
                     54: **     If a maximum buffer limit is reached Content-Length is calculated
                     55: **     for logs but it is not sent to the client -- rather the buffer is
                     56: **     flushed right away.
                     57: **     Code taken from HTRequest.c written by Ari Luotonen and modified to
                     58: **     fit new stream model
                     59: */
                     60: 
                     61: PRIVATE BOOL free_buf (HTBufItem * me)
                     62: {
                     63:     if (me) {
                     64:        FREE(me->buf);
                     65:        free(me);
                     66:        return YES;
                     67:     }
                     68:     return NO;
                     69: }
                     70: 
                     71: PRIVATE void free_buf_all (HTStream * me)
                     72: {
                     73:     HTBufItem * cur = me->head;
                     74:     HTBufItem * killme;
                     75:     while (cur) {
                     76:        killme = cur;
                     77:        cur = cur->next;
                     78:        free_buf(cur);
                     79:     }
                     80:     me->head = me->tail = NULL;
                     81: }
                     82: 
                     83: PRIVATE void append_buf (HTStream * me)
                     84: {
                     85:     HTBufItem * b = (HTBufItem *) calloc(1, sizeof(HTBufItem));
                     86:     if (!b) outofmem(__FILE__, "append_buf");
                     87:     b->len = me->tmp_ind;
                     88:     b->buf = me->tmp_buf;
                     89:     me->tmp_ind = 0;
                     90:     me->tmp_max = 0;
                     91:     me->tmp_buf = 0;
                     92:     if (me->tail)
                     93:        me->tail->next = b;
                     94:     else
                     95:        me->head = b;
                     96:     me->tail = b;
                     97: }
                     98: 
                     99: PRIVATE BOOL alloc_new (HTStream * me, int size)
                    100: {
                    101:     if (me->conlen >= me->max_size) {
                    102:        if (STREAM_TRACE)
2.2       frystyk   103:            TTYPrint(TDEST,"StreamBuffer limit %d reached, going transparent\n",
2.1       frystyk   104:                    me->max_size);
                    105:        return NO;
                    106:     } else if (size) {
                    107:        me->tmp_ind = 0;
                    108:        me->tmp_max = size;
                    109:        me->tmp_buf = (char *) malloc(size);
                    110:        if (!me->tmp_buf) outofmem(__FILE__, "buf_put_char");
                    111:        if (STREAM_TRACE)
2.2       frystyk   112:            TTYPrint(TDEST, "StreamBuffer created with len %d\n", size);
2.1       frystyk   113:        return YES;
                    114:     }
                    115:     return NO;
                    116: }
                    117: 
                    118: PRIVATE int buf_flush (HTStream * me)
                    119: {
                    120:     HTBufItem * cur;
                    121:     if (me->tmp_buf) append_buf(me);
                    122:     while ((cur = me->head)) {
                    123:        int status = PUTBLOCK(cur->buf, cur->len);
                    124:        if (status != HT_OK) return status;
                    125:        me->head = cur->next;
                    126:        free_buf(cur);
                    127:     }
                    128:     return HT_OK;
                    129: }
                    130: 
                    131: PRIVATE int buf_put_block (HTStream * me, CONST char * b, int l)
                    132: {
                    133:     me->conlen += l;
                    134:     if (!me->give_up) {
                    135:        if (me->tmp_buf && me->tmp_max-me->tmp_ind >= l) {     /* Still room */
                    136:            memcpy(me->tmp_buf + me->tmp_ind, b, l);
                    137:            me->tmp_ind += l;
                    138:            return HT_OK;
                    139:        } else {
                    140:            if (me->tmp_buf) append_buf(me);
                    141:            if (me->cur_size < HT_MAX_BLOCK) {
                    142:                int newsize = me->cur_size ? me->cur_size : HT_MIN_BLOCK;
                    143:                while (l > newsize && newsize < HT_MAX_BLOCK) newsize *= 2;
                    144:                me->cur_size = newsize;
                    145:            }
                    146:            if (!alloc_new(me, me->cur_size)) {
                    147:                int status = buf_flush(me);
                    148:                if (status != HT_OK) return status;
                    149:                me->give_up = YES;
                    150:            } else {
                    151:                memcpy(me->tmp_buf, b, l);
                    152:                me->tmp_ind = l;
                    153:            }
                    154:        }
                    155:     }
                    156:     if (me->give_up) return PUTBLOCK(b, l);
                    157:     return HT_OK;
                    158: }
                    159: 
                    160: PRIVATE int buf_put_char (HTStream * me, char c)
                    161: {
                    162:     return buf_put_block(me, &c, 1);
                    163: }
                    164: 
                    165: PRIVATE int buf_put_string (HTStream * me, CONST char * s)
                    166: {
                    167:     return buf_put_block(me, s, (int) strlen(s));
                    168: }
                    169: 
                    170: PRIVATE int buf_free (HTStream * me)
                    171: {
                    172:     int status = HT_OK;
                    173:     if (!me->ignore) {
                    174:        HTParentAnchor *anchor = HTRequest_anchor(me->request);
                    175:        if (STREAM_TRACE)
2.2       frystyk   176:            TTYPrint(TDEST,"\nCalculated.. content-length: %d\n", me->conlen);
2.1       frystyk   177:        HTAnchor_setLength(anchor, me->conlen);
                    178:     }
                    179:     if (!me->give_up && (status = buf_flush(me)) != HT_OK)
                    180:        return status;
                    181:     if ((status = (*me->target->isa->_free)(me->target)) != HT_OK)
                    182:        return status;
                    183:     free(me);
                    184:     return status;
                    185: }
                    186: 
2.3     ! frystyk   187: PRIVATE int buf_abort (HTStream * me, HTList * e)
2.1       frystyk   188: {
                    189:     if (!me->give_up)
                    190:        free_buf_all(me);
                    191:     if (me->target)
                    192:        (*me->target->isa->abort)(me->target,e);
                    193:     free(me);
2.2       frystyk   194:     if (PROT_TRACE) TTYPrint(TDEST, "Length...... ABORTING...\n");
2.1       frystyk   195:     return HT_ERROR;
                    196: }
                    197: 
                    198: HTStreamClass HTContentCounterClass = {
                    199:     "ContentCounter",
                    200:     buf_flush,
                    201:     buf_free,
                    202:     buf_abort,
                    203:     buf_put_char,
                    204:     buf_put_string,
                    205:     buf_put_block
                    206: };
                    207: 
                    208: PUBLIC HTStream * HTContentCounter (HTStream * target,
                    209:                                    HTRequest * request,
                    210:                                    int         max_size)
                    211: {
                    212:     HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
                    213:     if (!me) outofmem(__FILE__, "HTContentCounter");
                    214:     me->isa = &HTContentCounterClass;
                    215:     me->target = target;
                    216:     me->request = request;
                    217:     me->max_size = (max_size > 0) ? max_size : HT_MAX_SIZE;
                    218:     if (STREAM_TRACE)
2.2       frystyk   219:        TTYPrint(TDEST, "Buffer...... Created with size %d\n", me->max_size);
2.1       frystyk   220:     return me;
                    221: }
                    222: 
                    223: PUBLIC HTStream * HTBuffer_new (HTStream *     target,
                    224:                                HTRequest *     request,
                    225:                                int             max_size)
                    226: {
                    227:     HTStream * me = HTContentCounter(target, request, max_size);
                    228:     if (me) me->ignore = YES;
                    229:     return me;
                    230: }

Webmaster