source: trunk/third/libghttp/http_resp.c @ 15592

Revision 15592, 20.1 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15591, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * http_resp.c -- routines for reading http_responses
3 * Created: Christopher Blizzard <blizzard@appliedtheory.com> 9-Aug-1998
4 *
5 * Copyright (C) 1998 Free Software Foundation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#include <unistd.h>
26#include "http_resp.h"
27#include "http_global.h"
28
29typedef enum header_state_tag
30{
31  reading_header = 0,
32  reading_value,
33  reading_sep,
34  reading_eol
35} header_state;
36
37static int
38string_is_number(char *a_string);
39
40static int
41read_chunk(http_trans_conn *a_conn);
42
43static int
44read_body_chunked(http_resp *a_resp,
45                  http_req *a_req,
46                  http_trans_conn *a_conn);
47
48static int
49read_body_content_length(http_resp *a_resp,
50                         http_req *a_req,
51                         http_trans_conn *a_conn);
52
53static int
54read_body_standard(http_resp *a_resp,
55                   http_req *a_req,
56                   http_trans_conn *a_conn);
57
58http_resp *
59http_resp_new(void)
60{
61  http_resp *l_return = NULL;
62
63  l_return = (http_resp *)malloc(sizeof(http_resp));
64  memset(l_return, 0, sizeof(http_resp));
65  l_return->headers = http_hdr_list_new();
66  return l_return;
67}
68
69void
70http_resp_destroy(http_resp *a_resp)
71{
72  if (!a_resp)
73    return;
74  if (a_resp->reason_phrase)
75    free(a_resp->reason_phrase);
76  if (a_resp->headers)
77    http_hdr_list_destroy(a_resp->headers);
78  if (a_resp->body)
79    free(a_resp->body);
80  free(a_resp);
81  return;
82}
83
84int
85http_resp_read_headers(http_resp *a_resp, http_trans_conn *a_conn)
86{
87  char          *l_start_body = NULL;
88  int            l_rv = 0;
89  int            l_done = 0;
90  int            l_return = HTTP_TRANS_DONE;
91  char          *l_start_header = NULL;
92  int            l_header_len = 0;
93  char          *l_last_header = NULL;
94  int            l_last_header_len = 0;
95  char          *l_start_value = NULL;
96  int            l_value_len = 0;
97  char          *l_cur_ptr = NULL;
98  char          *l_ptr = NULL;
99  header_state   l_state = reading_header;
100
101  /* check to see if we need to jump in somewhere */
102  if (a_conn->sync == HTTP_TRANS_ASYNC)
103    {
104      if (a_resp->header_state == http_resp_reading_header)
105        goto http_resp_reading_header_jump;
106    }
107  /* start reading headers */
108  do
109    {
110      a_resp->header_state = http_resp_reading_header;
111    http_resp_reading_header_jump:
112      /* read in the buffer */
113      l_rv = http_trans_read_into_buf(a_conn);
114      /* check for an error */
115      if (l_rv == HTTP_TRANS_ERR)
116        {
117          a_conn->errstr = "Failed to read http response line";
118          l_return = HTTP_TRANS_ERR;
119          goto ec;
120        }
121      /* check to see if the end of headers string is in the buffer */
122      l_start_body = http_trans_buf_has_patt(a_conn->io_buf,
123                                             a_conn->io_buf_alloc,
124                                             "\r\n\r\n", 4);
125      if (l_start_body != NULL)
126        l_done = 1;
127      if ((l_done == 0) && (a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
128        return HTTP_TRANS_NOT_DONE;
129      /* yes, that !l_done is ther because in the case of a 100
130         continue we well get back up to this loop without doing a
131         successful read. */
132      if ((!l_done) && (l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
133        {
134          a_conn->errstr = "Short read while reading http response headers";
135          return HTTP_TRANS_ERR;
136        }
137    } while (l_done == 0);
138  /* parse out the response header */
139  /* check to make sure that there's enough that came back */
140  if ((a_conn->io_buf_alloc) < 14)
141    {
142      a_conn->errstr = "The http response line was too short.";
143      l_return = HTTP_TRANS_ERR;
144      goto ec;
145    }
146  l_ptr = a_conn->io_buf;
147  /* can you say PARANOID?  I thought you could. */
148  if (strncmp(l_ptr, "HTTP", 4) != 0)
149    {
150      a_conn->errstr = "The http response line did not begin with \"HTTP\"";
151      l_return = HTTP_TRANS_ERR;
152      goto ec;
153    }
154  if ((isdigit(l_ptr[5]) == 0) || /* http ver */
155      (l_ptr[6] != '.') ||
156      (isdigit(l_ptr[7]) == 0) ||
157      (l_ptr[8] != ' ') ||        /* space */
158      (isdigit(l_ptr[9]) == 0) || /* code */
159      (isdigit(l_ptr[10]) == 0) ||
160      (isdigit(l_ptr[11]) == 0) ||
161      (l_ptr[12] != ' '))          /* space */
162    {
163      a_conn->errstr = "Error parsing http response line";
164      l_return = HTTP_TRANS_ERR;
165      goto ec;
166    }
167  /* convert char into int */
168  a_resp->http_ver = (l_ptr[5] - 0x30);
169  a_resp->http_ver += ((l_ptr[7] - 0x30) / 10.0);
170  /* convert the response into an int */
171  a_resp->status_code = ((l_ptr[9] - 0x30)*100);
172  a_resp->status_code += ((l_ptr[10] - 0x30)*10);
173  a_resp->status_code += (l_ptr[11] - 0x30);
174  /* get the length of the reason_phrase */
175  l_cur_ptr = &l_ptr[13];
176  /* you can't overrun this because you already know that
177     there has to be a '\r' above from searching from the
178     end of the headers */
179  while (*l_cur_ptr != '\r')
180    l_cur_ptr++;
181  /* make sure to free the buffer if it's already allocated */
182  if (a_resp->reason_phrase) {
183    free(a_resp->reason_phrase);
184    a_resp->reason_phrase = NULL;
185  }
186  /* allocate space for the reason phrase */
187  a_resp->reason_phrase =
188    malloc((l_cur_ptr - (&l_ptr[13])) + 1);
189  memset(a_resp->reason_phrase, 0,
190         ((l_cur_ptr - (&l_ptr[13])) + 1));
191  memcpy(a_resp->reason_phrase,
192         &l_ptr[13], (l_cur_ptr - (&l_ptr[13])));
193  /* see if there are any headers.  If there aren't any headers
194     then the end of the reason phrase is the same as the start body
195     as above.  If that's the case then skip reading any headers. */
196  if (l_cur_ptr == l_start_body)
197    l_done = 1;
198  else
199    l_done = 0;
200  /* make sure that it's not a continue. */
201  if (a_resp->status_code == 100)
202    {
203      /* look for the next \r\n\r\n and cut it off */
204      char *l_end_continue = http_trans_buf_has_patt(a_conn->io_buf,
205                                                     a_conn->io_buf_alloc,
206                                                     "\r\n\r\n", 4);
207      if (!l_end_continue)
208        return HTTP_TRANS_ERR;
209      http_trans_buf_clip(a_conn, l_end_continue + 4);
210      l_start_body = NULL;
211      a_resp->status_code = 0;
212      l_done = 0;
213      if (a_conn->sync == HTTP_TRANS_ASYNC)
214        return HTTP_TRANS_NOT_DONE;
215      else
216        goto http_resp_reading_header_jump;
217    }
218  /* set the start past the end of the reason phrase,
219     checking if there's a CRLF after it. */
220  while ((*l_cur_ptr == '\r') ||
221         (*l_cur_ptr == '\n'))
222    l_cur_ptr++;
223
224  /* start parsing out the headers */
225  /* start at the beginning */
226  l_start_header = l_cur_ptr;
227  while (l_done == 0)
228    {
229      /* check to see if we're at the end of the
230         headers as determined above by the _patt() call */
231      if (l_cur_ptr == (l_start_body + 1))
232        break;
233      /* reading the header name */
234      if (l_state == reading_header)
235        {
236          /* check to see if there's leading whitespace.
237             If that's the case then it needs to be combined
238             from the previous header */
239          if (l_header_len == 0)
240            {
241              if ((*l_cur_ptr == ' ') || (*l_cur_ptr == '\t'))
242                {
243                  /* bomb if it's the first header.  That's not valid */
244                  if ((l_last_header == NULL) || (l_last_header_len == 0))
245                    {
246                      a_conn->errstr = "The first http response header began with whitespace";
247                      l_return = HTTP_TRANS_ERR;
248                      goto ec;
249                    }
250                  l_cur_ptr++;
251                  /* set it reading sep.  sep will eat all of the write space */
252                  l_state = reading_sep;
253                  continue;
254                }
255            }
256          if (*l_cur_ptr == ':')
257            {
258              /* make sure that there's some header there */
259              if (l_header_len == 0)
260                {
261                  a_conn->errstr = "An http response header was zero length";
262                  l_return = HTTP_TRANS_ERR;
263                  goto ec;
264                }
265              /* start reading the seperator */
266              l_state = reading_sep;
267              l_cur_ptr++;
268            }
269          /* make sure there's a seperator in
270             there somewhere */
271          else if (*l_cur_ptr == '\r')
272            {
273              a_conn->errstr = "Failed to find seperator in http response headers";
274              l_return = HTTP_TRANS_ERR;
275              goto ec;
276            }
277          else
278            {
279              l_cur_ptr++;
280              l_header_len++;
281            }
282        }
283      /* read the seperator */
284      else if(l_state == reading_sep)
285        {
286          /* walk until you get a non-whitespace character */
287          if ((*l_cur_ptr == ' ') || (*l_cur_ptr == '\t'))
288            l_cur_ptr++;
289          else
290            {
291              l_state = reading_value;
292              l_start_value = l_cur_ptr;
293              l_value_len = 0;
294            }
295        }
296      /* read the value */
297      else if(l_state == reading_value)
298        {
299          /* check to see if we've reached the end of the
300             value */
301          if ((*l_cur_ptr == '\r') || (*l_cur_ptr == '\n'))
302            {
303              /* check to see if this is a continuation of the last
304                 header. If the header len is 0 and we've gotten to
305                 this point then that's the case */
306              if (l_header_len == 0)
307                {
308                  http_hdr_set_value_no_nts(a_resp->headers,
309                                            l_last_header,
310                                            l_last_header_len,
311                                            l_start_value,
312                                            l_value_len);
313                }
314              else
315                {
316                  http_hdr_set_value_no_nts(a_resp->headers,
317                                            l_start_header,
318                                            l_header_len,
319                                            l_start_value,
320                                            l_value_len);
321                 
322                  /* set the last header and the length so that a new line
323                     that starts with spaces can figure out what header it
324                     applies to */
325                  l_last_header = l_start_header;
326                  l_last_header_len = l_header_len;
327                }
328              /* start eating the end of line */
329              l_state = reading_eol;
330            }
331          else
332            {
333              l_cur_ptr++;
334              l_value_len++;
335            }
336        }
337      /* read the eof */
338      else if(l_state == reading_eol)
339        {
340          /* eat the eol */
341          if ((*l_cur_ptr == '\r') || (*l_cur_ptr == '\n'))
342            l_cur_ptr++;
343          else
344            {
345              /* start reading a new header again. */
346              l_state = reading_header;
347              l_start_header = l_cur_ptr;
348              l_header_len = 0;
349            }
350        }
351      /* what state is this? */
352      else
353        {
354          a_conn->errstr = "Unknown state while reading http response headers";
355          l_return = HTTP_TRANS_ERR;
356          goto ec;
357        }
358    }
359  /* clip the buffer */
360  http_trans_buf_clip(a_conn, l_start_body + 4);
361 ec:
362  a_resp->header_state = http_resp_header_start;
363  return l_return;
364}
365
366int
367http_resp_read_body(http_resp *a_resp,
368                    http_req *a_req,
369                    http_trans_conn *a_conn)
370{
371  int      l_return = 0;
372  char    *l_content_length = NULL;
373  char    *l_transfer_encoding = NULL;
374  char    *l_connection = NULL;
375
376  /* check to see if we have to jump in anywhere. */
377  if (a_conn->sync == HTTP_TRANS_ASYNC)
378    {
379      if (a_resp->body_state == http_resp_body_read_content_length)
380        goto http_resp_body_read_content_length_jump;
381      if (a_resp->body_state == http_resp_body_read_chunked)
382        goto http_resp_body_read_chunked_jump;
383      if (a_resp->body_state == http_resp_body_read_standard)
384        goto http_resp_body_read_standard_jump;
385    }
386  /* check to make sure that things are ok. */
387  if ((!a_resp) || (!a_conn))
388    return -1;
389  /* check to see if there should be an entity body. */
390  /* check to see if there's a content length */
391  l_content_length =
392    http_hdr_get_value(a_resp->headers,
393                       http_hdr_Content_Length);
394  /* check to see if there's a transfer encoding */
395  l_transfer_encoding =
396    http_hdr_get_value(a_resp->headers,
397                       http_hdr_Transfer_Encoding);
398  /* check to see if the connection header is set */
399  l_connection =
400    http_hdr_get_value(a_resp->headers,
401                       http_hdr_Connection);
402  /* if there's a content length, do your stuff */
403  if (l_content_length && (a_req->type != http_req_type_head))
404    {
405      if (string_is_number(l_content_length) == 0)
406        {
407          a_conn->errstr = "Content length in http response was not a number";
408          return -1;
409        }
410      a_resp->content_length = atoi(l_content_length);
411      /* set the state */
412      a_resp->body_state = http_resp_body_read_content_length;
413    http_resp_body_read_content_length_jump:
414      l_return = read_body_content_length(a_resp, a_req, a_conn);
415    }
416  else if (l_content_length)
417    {
418      /* this happens in a head request with content length. */
419      return HTTP_TRANS_DONE;
420    }
421  else if (l_transfer_encoding)
422    {
423      /* check to see if it's using chunked transfer encoding */
424      if (!strcasecmp(l_transfer_encoding, "chunked"))
425        {
426          /* set the state */
427          a_resp->body_state = http_resp_body_read_chunked;
428        http_resp_body_read_chunked_jump:
429          l_return = read_body_chunked(a_resp, a_req, a_conn);
430        }
431      else
432        {
433          /* what kind of encoding? */
434          a_conn->errstr = "Unknown encoding type in http response";
435          return -1;
436        }
437    }
438  else
439    {
440      a_resp->body_state = http_resp_body_read_standard;
441      /* set the state */
442    http_resp_body_read_standard_jump:
443      l_return = read_body_standard(a_resp, a_req, a_conn);
444      /* after that the connection gets closed */
445      if (l_return == HTTP_TRANS_DONE)
446        {
447          close(a_conn->sock);
448          a_conn->sock = -1;
449        }
450    }
451  /* check to see if the connection should be closed */
452  if (l_connection && (l_return != HTTP_TRANS_NOT_DONE))
453    {
454      if (!strcasecmp(l_connection, "close"))
455        {
456          close (a_conn->sock);
457          a_conn->sock = -1;
458        }
459    }
460  if (l_return == HTTP_TRANS_DONE)
461    a_resp->body_state = http_resp_body_start;
462  return l_return;
463}
464
465static int
466string_is_number(char *a_string)
467{
468  int i = 0;
469 
470  if (strlen(a_string) < 1)
471    return 0;
472  while (a_string[i])
473    {
474      if (isdigit(a_string[i]) == 0)
475        return 0;
476      i++;
477    }
478  return 1;
479}
480
481static int
482read_chunk(http_trans_conn *a_conn)
483{
484  char *l_end_chunk_hdr = NULL;
485  int   l_len = 0;
486  int   i = 0;
487  int   j = 0;
488  char *l_ptr = NULL;
489  int   l_left_to_read = 0;
490  int   l_rv = 0;
491
492  if (a_conn->chunk_len == 0)
493    {
494      /* check to make sure that the pattern is in the
495         buffer */
496      do {
497        if ((l_end_chunk_hdr =
498             http_trans_buf_has_patt(a_conn->io_buf, a_conn->io_buf_alloc,
499                                     "\r\n", 2)) == NULL)
500          {
501            l_rv = http_trans_read_into_buf(a_conn);
502            if (l_rv == HTTP_TRANS_ERR)
503              return HTTP_TRANS_ERR;
504            /* check to see if the remote end hung up. */
505            if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
506              return HTTP_TRANS_ERR;
507            if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
508              return HTTP_TRANS_NOT_DONE;
509          }
510      } while (l_end_chunk_hdr == NULL);
511      /* set the begining at the start of the buffer */
512      l_ptr = a_conn->io_buf;
513      /* eat the hex value of the chunk */
514      while ((l_ptr < l_end_chunk_hdr) &&
515             (((tolower(*l_ptr) <= 'f') && (tolower(*l_ptr) >= 'a')) ||
516              ((*l_ptr <= '9') && (*l_ptr >= '0'))))
517        l_ptr++;
518      /* get the length of the hex number */
519      l_len = l_ptr - a_conn->io_buf;
520      if (l_len == 0)
521        {
522          a_conn->chunk_len = -1;
523          return HTTP_TRANS_ERR;
524        }
525      /* walk the size adding the values as you go along. */
526      for (i=0, j=l_len-1; i < l_len; i++, j--)
527        {
528          if ((tolower(a_conn->io_buf[i]) <= 'f') && (tolower(a_conn->io_buf[i]) >= 'a'))
529            a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x57) << (4*j);
530          else
531            a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x30) << (4*j);
532        }
533      /* reset the pointer past the end of the header */
534      http_trans_buf_clip(a_conn, l_end_chunk_hdr + 2);
535    }
536  /* check to see if it's the last chunk.  If not then add it.*/
537  if (a_conn->chunk_len != 0)
538    {
539      /* figure out how much we need to read */
540      /* the + 2 is for the \r\n that always follows a chunk. */
541      l_left_to_read = a_conn->chunk_len - a_conn->io_buf_alloc + 2;
542      /* check to make sure that we actually need to read anything in. */
543      if (l_left_to_read > 0)
544        {
545          /* set the vars in the struct */
546          a_conn->io_buf_io_left = l_left_to_read;
547          a_conn->io_buf_io_done = 0;
548          /* append it */
549          do {
550            l_rv = http_trans_read_into_buf(a_conn);
551            if (l_rv == HTTP_TRANS_ERR)
552              return HTTP_TRANS_ERR;
553            /* check and see if the server hung up. */
554            if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
555              return HTTP_TRANS_ERR;
556            if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
557              return HTTP_TRANS_NOT_DONE;
558          } while (l_rv == HTTP_TRANS_NOT_DONE);
559        }
560    }
561  if (a_conn->io_buf_alloc >= a_conn->chunk_len + 2)
562    return HTTP_TRANS_DONE;
563  /* we only get here if there was an error. */
564  if (a_conn->chunk_len == 0)
565    return HTTP_TRANS_DONE;
566  return HTTP_TRANS_ERR;
567}
568
569static int
570read_body_chunked(http_resp *a_resp,
571                  http_req *a_req,
572                  http_trans_conn *a_conn)
573{
574  int   l_rv = 0;
575  int   l_done = 0;
576 
577  do
578    {
579      /* read a chunk */
580      l_rv = read_chunk(a_conn);
581      if (l_rv == HTTP_TRANS_ERR)
582        return HTTP_TRANS_ERR;
583      if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
584        return HTTP_TRANS_NOT_DONE;
585      /* see if it's the first time */
586      if (a_conn->chunk_len > 0)
587        {
588          if (a_resp->body == NULL)
589            {
590              a_resp->body = malloc(a_conn->chunk_len);
591              memcpy(a_resp->body, a_conn->io_buf, a_conn->chunk_len);
592              a_resp->body_len = a_conn->chunk_len;
593            }
594          /* append it to the body */
595          else
596            {
597              a_resp->body = realloc(a_resp->body,
598                                     (a_resp->body_len + a_conn->chunk_len));
599              memcpy(&a_resp->body[a_resp->body_len], a_conn->io_buf, a_conn->chunk_len);
600              a_resp->body_len += a_conn->chunk_len;
601            }
602        }
603      /* make sure there's at least 2 bytes in the buffer.
604         This happens when a read was 3 bytes as in 0\r\n
605         and there is still 2 bytes ( \r\n ) in the read queue. */
606      if ((a_conn->chunk_len == 0) && (a_conn->io_buf_alloc < 2))
607        {
608          a_conn->io_buf_io_left = ( 2 - a_conn->io_buf_alloc );
609          a_conn->io_buf_io_done = 0;
610          do {
611            l_rv = http_trans_read_into_buf(a_conn);
612          } while (l_rv == HTTP_TRANS_NOT_DONE);
613          /* check for an error */
614          if (l_rv == HTTP_TRANS_ERR)
615            return HTTP_TRANS_ERR;
616        }
617      if (a_conn->chunk_len == 0)
618        l_done = 1;
619      else
620        {
621          /* clip the buffer */
622          http_trans_buf_clip(a_conn, &a_conn->io_buf[a_conn->chunk_len + 2]);
623        }
624      a_conn->chunk_len = 0;
625    } while (l_done == 0);
626  return HTTP_TRANS_DONE;
627}
628
629static void
630flush_response_body(http_resp *a_resp,
631                    http_trans_conn *a_conn)
632{
633  if (a_resp->body != NULL) {
634    free(a_resp->body);
635  }
636  a_resp->flushed_length += a_resp->body_len;
637  a_resp->body_len = a_conn->io_buf_alloc;
638  a_resp->body = malloc(a_conn->io_buf_alloc + 1);
639  memset(a_resp->body, 0, a_conn->io_buf_alloc + 1);
640  memcpy(a_resp->body, a_conn->io_buf, a_conn->io_buf_alloc);
641  /* clean the buffer */
642  http_trans_buf_reset(a_conn);
643}
644
645void
646http_resp_flush(http_resp *a_resp,
647                http_trans_conn *a_conn)
648{
649  flush_response_body(a_resp, a_conn);
650}
651
652static int
653read_body_content_length(http_resp *a_resp,
654                         http_req *a_req,
655                         http_trans_conn *a_conn)
656{
657  int l_len = 0;
658  int l_left_to_read = 0;
659  int l_rv = 0;
660
661  l_len = a_resp->content_length;
662  if (l_len == 0)
663    return HTTP_TRANS_DONE;
664
665  /* find out how much more we have to read */
666  l_left_to_read = l_len - a_conn->io_buf_alloc - a_resp->flushed_length - a_resp->body_len;
667  /* set the variables */
668  a_conn->io_buf_io_left = l_left_to_read;
669  a_conn->io_buf_io_done = 0;
670  if (l_left_to_read > 0)
671    {
672      /* append the rest of the body to the
673         buffer */
674      do {
675        l_rv = http_trans_read_into_buf(a_conn);
676        if ((l_rv == HTTP_TRANS_NOT_DONE) &&
677            (a_conn->sync == HTTP_TRANS_ASYNC))
678          return HTTP_TRANS_NOT_DONE;
679        if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
680          return HTTP_TRANS_ERR;
681      } while(l_rv == HTTP_TRANS_NOT_DONE);
682      if (l_rv == HTTP_TRANS_ERR)
683        return HTTP_TRANS_ERR;
684    }
685  /* write it into the body */
686  flush_response_body (a_resp, a_conn);
687  return HTTP_TRANS_DONE;
688}
689
690static int
691read_body_standard(http_resp *a_resp,
692                   http_req *a_req,
693                   http_trans_conn *a_conn)
694{
695  int l_rv = 0;
696  /* anything without a content length or chunked encoding */
697  do {
698    l_rv = http_trans_read_into_buf(a_conn);
699    if (a_conn->sync == HTTP_TRANS_ASYNC)
700      {
701        if ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read != 0))
702          return HTTP_TRANS_NOT_DONE;
703      }
704  } while ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read > 0));
705
706  if (l_rv == HTTP_TRANS_ERR)
707    return HTTP_TRANS_ERR;
708
709  flush_response_body(a_resp, a_conn);
710  return HTTP_TRANS_DONE;
711}
Note: See TracBrowser for help on using the repository browser.