source: mainline/uspace/lib/http/response.c@ 0005b63

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0005b63 was 0005b63, checked in by Martin Sucha <sucha14@…>, 12 years ago

libhttp: make header api a little bit more flexible

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup http
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <str.h>
39#include <macros.h>
40
41#include "http.h"
42
43int http_parse_status(const char *line, http_version_t *out_version,
44 uint16_t *out_status, char **out_message)
45{
46 http_version_t version;
47 uint16_t status;
48 char *message = NULL;
49
50 if (!str_test_prefix(line, "HTTP/"))
51 return EINVAL;
52
53 const char *pos_version = line + 5;
54 const char *pos = pos_version;
55
56 int rc = str_uint8_t(pos_version, &pos, 10, false, &version.major);
57 if (rc != EOK)
58 return rc;
59 if (*pos != '.')
60 return EINVAL;
61 pos++;
62
63 pos_version = pos;
64 rc = str_uint8_t(pos_version, &pos, 10, false, &version.minor);
65 if (rc != EOK)
66 return rc;
67 if (*pos != ' ')
68 return EINVAL;
69 pos++;
70
71 const char *pos_status = pos;
72 rc = str_uint16_t(pos_status, &pos, 10, false, &status);
73 if (rc != EOK)
74 return rc;
75 if (*pos != ' ')
76 return EINVAL;
77 pos++;
78
79 if (out_message) {
80 message = str_dup(pos);
81 if (message == NULL)
82 return ENOMEM;
83 }
84
85 if (out_version)
86 *out_version = version;
87 if (out_status)
88 *out_status = status;
89 if (out_message)
90 *out_message = message;
91 return EOK;
92}
93
94int http_receive_response(http_t *http, http_response_t **out_response)
95{
96 http_response_t *resp = malloc(sizeof(http_response_t));
97 if (resp == NULL)
98 return ENOMEM;
99 memset(resp, 0, sizeof(http_response_t));
100 list_initialize(&resp->headers);
101
102 char *line = malloc(http->buffer_size);
103 if (line == NULL) {
104 free(resp);
105 return ENOMEM;
106 }
107
108 int rc = recv_line(&http->recv_buffer, line, http->buffer_size);
109 if (rc < 0)
110 goto error;
111
112 rc = http_parse_status(line, &resp->version, &resp->status,
113 &resp->message);
114 if (rc != EOK)
115 goto error;
116
117 while (true) {
118 rc = recv_line(&http->recv_buffer, line, http->buffer_size);
119 if (rc < 0)
120 goto error;
121 if (*line == 0)
122 break;
123
124 http_header_t *header = malloc(sizeof(http_header_t));
125 if (header == NULL) {
126 rc = ENOMEM;
127 goto error;
128 }
129 http_header_init(header);
130
131 rc = http_header_parse(line, header);
132 if (rc != EOK)
133 goto error;
134
135 list_append(&header->link, &resp->headers);
136 }
137
138 *out_response = resp;
139
140 return EOK;
141error:
142 free(line);
143 http_response_destroy(resp);
144 return rc;
145}
146
147int http_receive_body(http_t *http, void *buf, size_t buf_size)
148{
149 return recv_buffer(&http->recv_buffer, buf, buf_size);
150}
151
152void http_response_destroy(http_response_t *resp)
153{
154 free(resp->message);
155 link_t *link = resp->headers.head.next;
156 while (link != &resp->headers.head) {
157 link_t *next = link->next;
158 http_header_t *header = list_get_instance(link, http_header_t, link);
159 http_header_destroy(header);
160 link = next;
161 }
162 free(resp);
163}
164
165/** @}
166 */
Note: See TracBrowser for help on using the repository browser.