source: mainline/uspace/lib/http/src/response.c

Last change on this file was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 5.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 <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <str.h>
40#include <macros.h>
41
42#include <http/http.h>
43
44static bool is_digit(char c)
45{
46 return (c >= '0' && c <= '9');
47}
48
49static errno_t 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 errno_t rc = recv_while(rb, is_digit);
56 if (rc != EOK) {
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 errno_t receive_uint8_t(receive_buffer_t *rb, uint8_t *out_value)
69{
70 char *str = NULL;
71 errno_t 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 errno_t receive_uint16_t(receive_buffer_t *rb, uint16_t *out_value)
83{
84 char *str = NULL;
85 errno_t 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 errno_t expect(receive_buffer_t *rb, const char *expect)
97{
98 size_t ndisc;
99 errno_t rc = recv_discard_str(rb, expect, &ndisc);
100 if (rc != EOK)
101 return rc;
102 if (ndisc < str_length(expect))
103 return HTTP_EPARSE;
104 return EOK;
105}
106
107static bool is_not_newline(char c)
108{
109 return (c != '\n' && c != '\r');
110}
111
112errno_t http_receive_status(receive_buffer_t *rb, http_version_t *out_version,
113 uint16_t *out_status, char **out_message)
114{
115 http_version_t version;
116 uint16_t status;
117 char *message = NULL;
118
119 errno_t rc = expect(rb, "HTTP/");
120 if (rc != EOK)
121 return rc;
122
123 rc = receive_uint8_t(rb, &version.major);
124 if (rc != EOK)
125 return rc;
126
127 rc = expect(rb, ".");
128 if (rc != EOK)
129 return rc;
130
131 rc = receive_uint8_t(rb, &version.minor);
132 if (rc != EOK)
133 return rc;
134
135 rc = expect(rb, " ");
136 if (rc != EOK)
137 return rc;
138
139 rc = receive_uint16_t(rb, &status);
140 if (rc != EOK)
141 return rc;
142
143 rc = expect(rb, " ");
144 if (rc != EOK)
145 return rc;
146
147 receive_buffer_mark_t msg_start;
148 recv_mark(rb, &msg_start);
149
150 rc = recv_while(rb, is_not_newline);
151 if (rc != EOK) {
152 recv_unmark(rb, &msg_start);
153 return rc;
154 }
155
156 receive_buffer_mark_t msg_end;
157 recv_mark(rb, &msg_end);
158
159 if (out_message) {
160 rc = recv_cut_str(rb, &msg_start, &msg_end, &message);
161 if (rc != EOK) {
162 recv_unmark(rb, &msg_start);
163 recv_unmark(rb, &msg_end);
164 return rc;
165 }
166 }
167
168 recv_unmark(rb, &msg_start);
169 recv_unmark(rb, &msg_end);
170
171 size_t nrecv;
172 rc = recv_eol(rb, &nrecv);
173 if (rc == EOK && nrecv == 0)
174 rc = HTTP_EPARSE;
175 if (rc != EOK) {
176 free(message);
177 return rc;
178 }
179
180 if (out_version)
181 *out_version = version;
182 if (out_status)
183 *out_status = status;
184 if (out_message)
185 *out_message = message;
186 return EOK;
187}
188
189errno_t http_receive_response(receive_buffer_t *rb, http_response_t **out_response,
190 size_t max_headers_size, unsigned max_headers_count)
191{
192 http_response_t *resp = malloc(sizeof(http_response_t));
193 if (resp == NULL)
194 return ENOMEM;
195 memset(resp, 0, sizeof(http_response_t));
196 http_headers_init(&resp->headers);
197
198 errno_t rc = http_receive_status(rb, &resp->version, &resp->status,
199 &resp->message);
200 if (rc != EOK)
201 goto error;
202
203 rc = http_headers_receive(rb, &resp->headers, max_headers_size,
204 max_headers_count);
205 if (rc != EOK)
206 goto error;
207
208 size_t nrecv;
209 rc = recv_eol(rb, &nrecv);
210 if (rc == EOK && nrecv == 0)
211 rc = HTTP_EPARSE;
212 if (rc != EOK)
213 goto error;
214
215 *out_response = resp;
216
217 return EOK;
218error:
219 http_response_destroy(resp);
220 return rc;
221}
222
223void http_response_destroy(http_response_t *resp)
224{
225 free(resp->message);
226 http_headers_clear(&resp->headers);
227 free(resp);
228}
229
230/** @}
231 */
Note: See TracBrowser for help on using the repository browser.