HTConLen.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:6k
源码类别:

浏览器

开发平台:

Unix_Linux

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