Changeset 3ce68b7 in mainline for uspace/lib/http/receive-buffer.c


Ignore:
Timestamp:
2013-09-26T09:01:36Z (11 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b623b68
Parents:
c17469e
Message:

libhttp: receive headers correctly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/http/receive-buffer.c

    rc17469e r3ce68b7  
    3939#include <errno.h>
    4040#include <macros.h>
     41#include <adt/list.h>
    4142
    4243#include "receive-buffer.h"
     
    5152        rb->out = 0;
    5253        rb->size = buffer_size;
     54       
     55        list_initialize(&rb->marks);
     56       
    5357        rb->buffer = malloc(buffer_size);
    5458        if (rb->buffer == NULL)
     
    5761}
    5862
     63static ssize_t dummy_receive(void *unused, void *buf, size_t buf_size)
     64{
     65        return 0;
     66}
     67
     68int recv_buffer_init_const(receive_buffer_t *rb, void *buf, size_t size)
     69{
     70        int rc = recv_buffer_init(rb, size, dummy_receive, NULL);
     71        if (rc != EOK)
     72                return rc;
     73       
     74        memcpy(rb->buffer, buf, size);
     75        rb->in = size;
     76        return EOK;
     77}
     78
    5979void recv_buffer_fini(receive_buffer_t *rb)
    6080{
     
    6888}
    6989
     90void recv_mark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
     91{
     92        link_initialize(&mark->link);
     93        list_append(&mark->link, &rb->marks);
     94        recv_mark_update(rb, mark);
     95}
     96
     97void recv_unmark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
     98{
     99        list_remove(&mark->link);
     100}
     101
     102void recv_mark_update(receive_buffer_t *rb, receive_buffer_mark_t *mark)
     103{
     104        mark->offset = rb->out;
     105}
     106
     107int recv_cut(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, void **out_buf, size_t *out_size)
     108{
     109        if (a->offset > b->offset)
     110                return EINVAL;
     111       
     112        size_t size = b->offset - a->offset;
     113        void *buf = malloc(size);
     114        if (buf == NULL)
     115                return ENOMEM;
     116       
     117        memcpy(buf, rb->buffer + a->offset, size);
     118        *out_buf = buf;
     119        *out_size = size;
     120        return EOK;
     121}
     122
     123int recv_cut_str(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, char **out_buf)
     124{
     125        if (a->offset > b->offset)
     126                return EINVAL;
     127       
     128        size_t size = b->offset - a->offset;
     129        char *buf = malloc(size + 1);
     130        if (buf == NULL)
     131                return ENOMEM;
     132       
     133        memcpy(buf, rb->buffer + a->offset, size);
     134        buf[size] = 0;
     135        for (size_t i = 0; i < size; i++) {
     136                if (buf[i] == 0) {
     137                        free(buf);
     138                        return EIO;
     139                }
     140        }
     141        *out_buf = buf;
     142        return EOK;
     143}
     144
     145
    70146/** Receive one character (with buffering) */
    71147int recv_char(receive_buffer_t *rb, char *c, bool consume)
    72148{
    73149        if (rb->out == rb->in) {
    74                 recv_reset(rb);
     150                size_t free = rb->size - rb->in;
     151                if (free == 0) {
     152                        size_t min_mark = rb->size;
     153                        list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
     154                                min_mark = min(min_mark, mark->offset);
     155                        }
     156                       
     157                        if (min_mark == 0)
     158                                return ELIMIT;
     159                       
     160                        size_t new_in = rb->in - min_mark;
     161                        memmove(rb->buffer, rb->buffer + min_mark, new_in);
     162                        rb->out = rb->in = new_in;
     163                        free = rb->size - rb->in;
     164                        list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
     165                                mark->offset -= min_mark;
     166                        }
     167                }
    75168               
    76                 ssize_t rc = rb->receive(rb->client_data, rb->buffer, rb->size);
     169                ssize_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free);
    77170                if (rc <= 0)
    78171                        return rc;
     
    100193}
    101194
    102 /** Receive a character and if it is c, discard it from input buffer */
    103 int recv_discard(receive_buffer_t *rb, char discard)
     195/** Receive a character and if it is c, discard it from input buffer
     196 * @return number of characters discarded (0 or 1) or negative error code
     197 */
     198ssize_t recv_discard(receive_buffer_t *rb, char discard)
    104199{
    105200        char c = 0;
     
    108203                return rc;
    109204        if (c != discard)
    110                 return EOK;
    111         return recv_char(rb, &c, true);
     205                return 0;
     206        rc = recv_char(rb, &c, true);
     207        if (rc != EOK)
     208                return rc;
     209        return 1;
     210}
     211
     212/** Receive an end of line, either CR, LF, CRLF or LFCR
     213 *
     214 * @return number of bytes read (0 if no newline is present in the stream)
     215 *         or negative error code
     216 */
     217ssize_t recv_eol(receive_buffer_t *rb)
     218{
     219        char c = 0;
     220        int rc = recv_char(rb, &c, false);
     221        if (rc != EOK)
     222                return rc;
     223       
     224        if (c != '\r' && c != '\n')
     225                return 0;
     226       
     227        rc = recv_char(rb, &c, true);
     228        if (rc != EOK)
     229                return rc;
     230       
     231        ssize_t rc2 = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
     232        if (rc2 < 0)
     233                return rc2;
     234       
     235        return 1 + rc2;
    112236}
    113237
Note: See TracChangeset for help on using the changeset viewer.