Changeset 408424e in mainline


Ignore:
Timestamp:
2013-09-26T23:31:50Z (11 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c42f50d
Parents:
4d4f656
Message:

libhttp: reimplement receiving status

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/download/main.c

    r4d4f656 r408424e  
    171171       
    172172        http_response_t *response = NULL;
    173         rc = http_receive_response(http, &response);
     173        rc = http_receive_response(&http->recv_buffer, &response);
    174174        if (rc != EOK) {
    175175                fprintf(stderr, "Failed receiving response: %s\n", str_error(rc));
     
    192192               
    193193                int body_size;
    194                 while ((body_size = http_receive_body(http, buf, buf_size)) > 0) {
     194                while ((body_size = recv_buffer(&http->recv_buffer, buf, buf_size)) > 0) {
    195195                        fwrite(buf, 1, body_size, stdout);
    196196                }
  • uspace/lib/http/include/http/http.h

    r4d4f656 r408424e  
    124124extern int http_request_format(http_request_t *, char **, size_t *);
    125125extern int http_send_request(http_t *, http_request_t *);
    126 extern int http_parse_status(const char *, http_version_t *, uint16_t *,
     126extern int http_receive_status(receive_buffer_t *, http_version_t *, uint16_t *,
    127127    char **);
    128 extern int http_receive_response(http_t *, http_response_t **);
    129 extern int http_receive_body(http_t *, void *, size_t);
     128extern int http_receive_response(receive_buffer_t *, http_response_t **);
    130129extern void http_response_destroy(http_response_t *);
    131130extern int http_close(http_t *);
  • uspace/lib/http/include/http/receive-buffer.h

    r4d4f656 r408424e  
    6565} receive_buffer_mark_t;
    6666
     67typedef bool (*char_class_func_t)(char);
     68
    6769extern int recv_buffer_init(receive_buffer_t *, size_t, receive_func_t, void *);
    6870extern int recv_buffer_init_const(receive_buffer_t *, void *, size_t);
     
    7981extern ssize_t recv_buffer(receive_buffer_t *, char *, size_t);
    8082extern ssize_t recv_discard(receive_buffer_t *, char);
     83extern ssize_t recv_discard_str(receive_buffer_t *, const char *);
     84extern ssize_t recv_while(receive_buffer_t *, char_class_func_t);
    8185extern ssize_t recv_eol(receive_buffer_t *);
    8286extern ssize_t recv_line(receive_buffer_t *, char *, size_t);
    83 
    84 
    8587
    8688#endif
  • uspace/lib/http/src/receive-buffer.c

    r4d4f656 r408424e  
    210210}
    211211
     212/** Receive a prefix of constant string discard and return number of bytes read
     213 * @return number of characters discarded or negative error code
     214 */
     215ssize_t recv_discard_str(receive_buffer_t *rb, const char *discard)
     216{
     217        size_t discarded = 0;
     218        while (*discard) {
     219                ssize_t rc = recv_discard(rb, *discard);
     220                if (rc < 0)
     221                        return rc;
     222                if (rc == 0)
     223                        break;
     224                discarded++;
     225                discard++;
     226        }
     227        return discarded;
     228}
     229
     230ssize_t recv_while(receive_buffer_t *rb, char_class_func_t class)
     231{
     232        size_t received = 0;
     233       
     234        while (true) {
     235                char c = 0;
     236                int rc = recv_char(rb, &c, false);
     237                if (rc != EOK)
     238                        return rc;
     239               
     240                if (!class(c))
     241                        break;
     242               
     243                rc = recv_char(rb, &c, true);
     244                if (rc != EOK)
     245                        return rc;
     246               
     247                received++;
     248        }
     249       
     250        return received;
     251}
     252
    212253/** Receive an end of line, either CR, LF, CRLF or LFCR
    213254 *
  • uspace/lib/http/src/response.c

    r4d4f656 r408424e  
    4242#include <http/errno.h>
    4343
    44 int http_parse_status(const char *line, http_version_t *out_version,
     44static bool is_digit(char c)
     45{
     46        return (c >= '0' && c <= '9');
     47}
     48
     49static int receive_number(receive_buffer_t *rb, char **str)
     50{
     51        receive_buffer_mark_t start;
     52        receive_buffer_mark_t end;
     53       
     54        recv_mark(rb, &start);
     55        int rc = recv_while(rb, is_digit);
     56        if (rc < 0) {
     57                recv_unmark(rb, &start);
     58                return rc;
     59        }
     60        recv_mark(rb, &end);
     61       
     62        rc = recv_cut_str(rb, &start, &end, str);
     63        recv_unmark(rb, &start);
     64        recv_unmark(rb, &end);
     65        return rc;
     66}
     67
     68static int receive_uint8_t(receive_buffer_t *rb, uint8_t *out_value)
     69{
     70        char *str = NULL;
     71        int rc = receive_number(rb, &str);
     72       
     73        if (rc != EOK)
     74                return rc;
     75       
     76        rc = str_uint8_t(str, NULL, 10, true, out_value);
     77        free(str);
     78       
     79        return rc;
     80}
     81
     82static int receive_uint16_t(receive_buffer_t *rb, uint16_t *out_value)
     83{
     84        char *str = NULL;
     85        int rc = receive_number(rb, &str);
     86       
     87        if (rc != EOK)
     88                return rc;
     89       
     90        rc = str_uint16_t(str, NULL, 10, true, out_value);
     91        free(str);
     92       
     93        return rc;
     94}
     95
     96static int expect(receive_buffer_t *rb, const char *expect)
     97{
     98        int rc = recv_discard_str(rb, expect);
     99        if (rc < 0)
     100                return rc;
     101        if ((size_t) rc < str_length(expect))
     102                return HTTP_EPARSE;
     103        return EOK;
     104}
     105
     106static bool is_not_newline(char c)
     107{
     108        return (c != '\n' && c != '\r');
     109}
     110
     111int http_receive_status(receive_buffer_t *rb, http_version_t *out_version,
    45112    uint16_t *out_status, char **out_message)
    46113{
     
    49116        char *message = NULL;
    50117       
    51         if (!str_test_prefix(line, "HTTP/"))
    52                 return EINVAL;
    53        
    54         const char *pos_version = line + 5;
    55         const char *pos = pos_version;
    56        
    57         int rc = str_uint8_t(pos_version, &pos, 10, false, &version.major);
    58         if (rc != EOK)
    59                 return rc;
    60         if (*pos != '.')
    61                 return EINVAL;
    62         pos++;
    63        
    64         pos_version = pos;
    65         rc = str_uint8_t(pos_version, &pos, 10, false, &version.minor);
    66         if (rc != EOK)
    67                 return rc;
    68         if (*pos != ' ')
    69                 return EINVAL;
    70         pos++;
    71        
    72         const char *pos_status = pos;
    73         rc = str_uint16_t(pos_status, &pos, 10, false, &status);
    74         if (rc != EOK)
    75                 return rc;
    76         if (*pos != ' ')
    77                 return EINVAL;
    78         pos++;
     118        int rc = expect(rb, "HTTP/");
     119        if (rc != EOK)
     120                return rc;
     121       
     122        rc = receive_uint8_t(rb, &version.major);
     123        if (rc != EOK)
     124                return rc;
     125       
     126        rc = expect(rb, ".");
     127        if (rc != EOK)
     128                return rc;
     129       
     130        rc = receive_uint8_t(rb, &version.minor);
     131        if (rc != EOK)
     132                return rc;
     133       
     134        rc = expect(rb, " ");
     135        if (rc != EOK)
     136                return rc;
     137       
     138        rc = receive_uint16_t(rb, &status);
     139        if (rc != EOK)
     140                return rc;
     141       
     142        rc = expect(rb, " ");
     143        if (rc != EOK)
     144                return rc;
     145       
     146        receive_buffer_mark_t msg_start;
     147        recv_mark(rb, &msg_start);
     148       
     149        rc = recv_while(rb, is_not_newline);
     150        if (rc < 0) {
     151                recv_unmark(rb, &msg_start);
     152                return rc;
     153        }
     154       
     155        receive_buffer_mark_t msg_end;
     156        recv_mark(rb, &msg_end);
    79157       
    80158        if (out_message) {
    81                 message = str_dup(pos);
    82                 if (message == NULL)
    83                         return ENOMEM;
     159                rc = recv_cut_str(rb, &msg_start, &msg_end, &message);
     160                if (rc != EOK) {
     161                        recv_unmark(rb, &msg_start);
     162                        recv_unmark(rb, &msg_end);
     163                        return rc;
     164                }
     165        }
     166       
     167        recv_unmark(rb, &msg_start);
     168        recv_unmark(rb, &msg_end);
     169       
     170        rc = recv_eol(rb);
     171        if (rc == 0)
     172                rc = HTTP_EPARSE;
     173        if (rc < 0) {
     174                free(message);
     175                return rc;
    84176        }
    85177       
     
    93185}
    94186
    95 int http_receive_response(http_t *http, http_response_t **out_response)
     187int http_receive_response(receive_buffer_t *rb, http_response_t **out_response)
    96188{
    97189        http_response_t *resp = malloc(sizeof(http_response_t));
     
    101193        http_headers_init(&resp->headers);
    102194       
    103         char *line = malloc(http->buffer_size);
    104         if (line == NULL) {
    105                 free(resp);
    106                 return ENOMEM;
    107         }
    108        
    109         int rc = recv_line(&http->recv_buffer, line, http->buffer_size);
    110         if (rc < 0)
     195        int rc = http_receive_status(rb, &resp->version, &resp->status,
     196            &resp->message);
     197        if (rc != EOK)
    111198                goto error;
    112199       
    113         rc = http_parse_status(line, &resp->version, &resp->status,
    114             &resp->message);
     200        rc = http_headers_receive(rb, &resp->headers);
    115201        if (rc != EOK)
    116202                goto error;
    117203       
    118         rc = http_headers_receive(&http->recv_buffer, &resp->headers);
    119         if (rc != EOK)
    120                 goto error;
    121        
    122         rc = recv_eol(&http->recv_buffer);
     204        rc = recv_eol(rb);
    123205        if (rc == 0)
    124206                rc = HTTP_EPARSE;
     
    130212        return EOK;
    131213error:
    132         free(line);
    133214        http_response_destroy(resp);
    134215        return rc;
    135 }
    136 
    137 int http_receive_body(http_t *http, void *buf, size_t buf_size)
    138 {
    139         return recv_buffer(&http->recv_buffer, buf, buf_size);
    140216}
    141217
Note: See TracChangeset for help on using the changeset viewer.