1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
|
/*****************************************************************************
* message.h: HTTP request/response
*****************************************************************************
* Copyright (C) 2015 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdint.h>
/**
* \defgroup http_msg Messages
* HTTP messages, header formatting and parsing
* \ingroup http
* @{
* \file message.h
*/
struct vlc_http_msg;
struct block_t;
struct vlc_http_cookie_jar_t;
/**
* Creates an HTTP request.
*
* Allocates an HTTP request message.
*
* @param method request method (e.g. "GET")
* @param scheme protocol scheme (e.g. "https")
* @param authority target host (e.g. "www.example.com:8080")
* @param path request path (e.g. "/dir/page.html")
* @return an HTTP stream or NULL on allocation failure
*/
struct vlc_http_msg *
vlc_http_req_create(const char *method, const char *scheme,
const char *authority, const char *path) VLC_USED;
/**
* Creates an HTTP response.
*
* Allocates an HTTP response message.
*
* @param status HTTP status code
* @return an HTTP stream or NULL on allocation failure
*/
struct vlc_http_msg *vlc_http_resp_create(unsigned status) VLC_USED;
/**
* Destroys an HTTP message.
*/
void vlc_http_msg_destroy(struct vlc_http_msg *);
/**
* Formats a header field.
*
* Adds an HTTP message header to an HTTP request or response.
* All headers must be formatted before the message is sent.
*
* @param name header field name
* @param fmt printf-style format string
* @return 0 on success, -1 on error (out of memory)
*/
int vlc_http_msg_add_header(struct vlc_http_msg *, const char *name,
const char *fmt, ...) VLC_FORMAT(3,4);
/**
* Sets the agent field.
*
* Sets the User-Agent or Server header field.
*/
int vlc_http_msg_add_agent(struct vlc_http_msg *, const char *);
/**
* Gets the agent field.
*
* Gets the User-Agent or Server header field.
*/
const char *vlc_http_msg_get_agent(const struct vlc_http_msg *);
/**
* Parses a timestamp header field.
*
* @param name header field name
* @return a timestamp value, or -1 on error.
*/
time_t vlc_http_msg_get_time(const struct vlc_http_msg *, const char *name);
/**
* Adds a timestamp header field.
*
* @param name header field name
* @param t pointer to timestamp
* @return 0 on success, -1 on error (errno is set accordingly)
*/
int vlc_http_msg_add_time(struct vlc_http_msg *, const char *name,
const time_t *t);
/**
* Adds a Date header field.
*/
int vlc_http_msg_add_atime(struct vlc_http_msg *);
/**
* Gets message date.
*
* Extracts the original date of the message from the HTTP Date header.
*
* @return a time value on success, -1 on error.
*/
time_t vlc_http_msg_get_atime(const struct vlc_http_msg *);
/**
* Gets resource date.
*
* Extracts the last modification date of the message content from the HTTP
* Last-Modified header.
*
* @return a time value on success, -1 on error.
*/
time_t vlc_http_msg_get_mtime(const struct vlc_http_msg *);
/**
* Gets retry timeout.
*
* Extracts the time (in seconds) until the expiration of the "retry-after"
* time-out in the HTTP message. If the header value is an absolute date, it
* is converted relative to the current time.
*
* @return the time in seconds, zero if the date is overdue or on error.
*/
unsigned vlc_http_msg_get_retry_after(const struct vlc_http_msg *);
void vlc_http_msg_get_cookies(const struct vlc_http_msg *,
struct vlc_http_cookie_jar_t *,
const char *host, const char *path);
int vlc_http_msg_add_cookies(struct vlc_http_msg *,
struct vlc_http_cookie_jar_t *);
char *vlc_http_msg_get_basic_realm(const struct vlc_http_msg *);
/**
* Adds Basic credentials.
*
* Formats a plain username and password pair using HTTP Basic (RFC7617)
* syntax.
*
* @param proxy true for proxy authentication,
* false for origin server authentication
* @param username null-terminated username
* @param password null-terminated password
* @return 0 on success, -1 on out-of-memory (ENOMEM) or if username or
* password are invalid (EINVAL).
*/
int vlc_http_msg_add_creds_basic(struct vlc_http_msg *, bool proxy,
const char *username, const char *password);
/**
* Looks up an header field.
*
* Finds an HTTP header field by (case-insensitive) name inside an HTTP
* message header. If the message has more than one matching field, their value
* are folded (as permitted by protocol specifications).
*
* @return header field value (valid until message is destroyed),
* or NULL if no fields matched
*/
const char *vlc_http_msg_get_header(const struct vlc_http_msg *,
const char *name);
/**
* Gets response status code.
*
* @return status code (e.g. 404), or negative if request
*/
int vlc_http_msg_get_status(const struct vlc_http_msg *m);
/**
* Gets request method.
*
* @return request method (e.g. "GET"), or NULL if response
*/
const char *vlc_http_msg_get_method(const struct vlc_http_msg *);
/**
* Gets request scheme.
*
* @return request scheme (e.g. "https"), or NULL if absent
*/
const char *vlc_http_msg_get_scheme(const struct vlc_http_msg *);
/**
* Gets request authority.
*
* @return request authority (e.g. "www.example.com:8080"),
* or NULL if response
*/
const char *vlc_http_msg_get_authority(const struct vlc_http_msg *);
/**
* Gets request absolute path.
*
* @return request absolute path (e.g. "/index.html"), or NULL if absent
*/
const char *vlc_http_msg_get_path(const struct vlc_http_msg *);
/**
* Looks up a token in a header field.
*
* Finds the first occurrence of a token within a HTTP field header.
*
* @param field HTTP header field name
* @param token HTTP token name
* @return the first byte of the token if found, NULL if not found.
*/
const char *vlc_http_msg_get_token(const struct vlc_http_msg *,
const char *field, const char *token);
/**
* Finds next token.
*
* Finds the following token in a HTTP header field value.
*
* @return First character of the following token,
* or NULL if there are no further tokens
*/
const char *vlc_http_next_token(const char *);
/**
* Gets HTTP payload length.
*
* Determines the total length (in bytes) of the payload associated with the
* HTTP message.
*
* @return byte length, or (uintmax_t)-1 if unknown.
*/
uintmax_t vlc_http_msg_get_size(const struct vlc_http_msg *);
/**
* Gets next response headers.
*
* Discards the current response headers and gets the next set of response
* headers for the same request. This is intended for HTTP 1xx continuation
* responses and for message trailers.
*
* @param m current response headers (destroyed by the call)
*
* @return next response headers or NULL on error
*/
struct vlc_http_msg *vlc_http_msg_iterate(struct vlc_http_msg *) VLC_USED;
/**
* Gets final response headers.
*
* Skips HTTP 1xx continue headers until a final set of response headers is
* received. This is a convenience wrapper around vlc_http_msg_iterate() for
* use when continuation headers are not useful (e.g. GET or CONNECT).
*
* @param m current response headers or NULL
*
* @return the final response headers (m if it was already final),
* NULL if the parameter was NULL, or NULL on error
*/
struct vlc_http_msg *vlc_http_msg_get_final(struct vlc_http_msg *) VLC_USED;
/**
* Receives HTTP data.
*
* Dequeues the next block of data from an HTTP message. If no pending data has
* been received, waits until data is received, the stream ends or the
* underlying connection fails.
*
* @return data block
* @retval NULL on end-of-stream
* @retval vlc_http_error on fatal error
*/
struct block_t *vlc_http_msg_read(struct vlc_http_msg *) VLC_USED;
/** @} */
/**
* \defgroup http_stream Streams
* \ingroup http_connmgr
*
* HTTP request/response streams
*
* A stream is initiated by a client-side request header. It includes a
* final response header, possibly preceded by one or more continuation
* response headers. After the response header, a stream usually carries
* a response payload.
*
* A stream may also carry a request payload (this is not supported so far).
*
* The HTTP stream constitutes the interface between an HTTP connection and
* the higher-level HTTP messages layer.
* @{
*/
struct vlc_http_stream;
/**
* Error pointer value
*
* This is an error value for some HTTP functions that can return NULL in
* non-error circumstances. Another return value is necessary to express
* error/failure, which this is.
* This compares different to NULL and to any valid pointer.
*
* @warning Dereferencing this pointer is undefined.
*/
extern void *const vlc_http_error;
void vlc_http_msg_attach(struct vlc_http_msg *m, struct vlc_http_stream *s);
struct vlc_http_msg *vlc_http_msg_get_initial(struct vlc_http_stream *s)
VLC_USED;
/** HTTP stream callbacks
*
* Connection-specific callbacks for stream manipulation
*/
struct vlc_http_stream_cbs
{
struct vlc_http_msg *(*read_headers)(struct vlc_http_stream *);
struct block_t *(*read)(struct vlc_http_stream *);
void (*close)(struct vlc_http_stream *, bool abort);
};
/** HTTP stream */
struct vlc_http_stream
{
const struct vlc_http_stream_cbs *cbs;
};
/**
* Reads one message header.
*
* Reads the next message header of an HTTP stream from the network.
* There is always exactly one request header per stream. There is usually
* one response header per stream, except for continuation (1xx) headers.
*
* @warning The caller is responsible for reading headers at appropriate
* times as intended by the protocol. Failure to do so may result in protocol
* dead lock, and/or (HTTP 1.x) connection failure.
*/
static inline
struct vlc_http_msg *vlc_http_stream_read_headers(struct vlc_http_stream *s)
{
return s->cbs->read_headers(s);
}
/**
* Reads message payload data.
*
* Reads the next block of data from the message payload of an HTTP stream.
*
* @return a block of data (use block_Release() to free it)
* @retval NULL The end of the stream was reached.
* @retval vlc_http_error The stream encountered a fatal error.
*/
static inline struct block_t *vlc_http_stream_read(struct vlc_http_stream *s)
{
return s->cbs->read(s);
}
/**
* Closes an HTTP stream.
*
* Releases all resources associated or held by an HTTP stream. Any unread
* header or data is discarded.
*/
static inline void vlc_http_stream_close(struct vlc_http_stream *s, bool abort)
{
s->cbs->close(s, abort);
}
/** @} */
/**
* Formats an HTTP 1.1 message header.
*
* Formats an message header in HTTP 1.x format, using HTTP version 1.1.
*
* @param m message to format/serialize
* @param lenp location to write the length of the formatted message in bytes
* [OUT]
* @param proxied whether the message is meant for sending to a proxy rather
* than an origin (only relevant for requests)
* @return A heap-allocated nul-terminated string or *lenp bytes,
* or NULL on error
*/
char *vlc_http_msg_format(const struct vlc_http_msg *m, size_t *restrict lenp,
bool proxied) VLC_USED VLC_MALLOC;
/**
* Parses an HTTP 1.1 message header.
*/
struct vlc_http_msg *vlc_http_msg_headers(const char *msg) VLC_USED;
struct vlc_h2_frame;
/**
* Formats an HTTP 2.0 HEADER frame.
*/
struct vlc_h2_frame *vlc_http_msg_h2_frame(const struct vlc_http_msg *m,
uint_fast32_t stream_id, bool eos);
/**
* Parses an HTTP 2.0 header table.
*/
struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned count,
const char *const headers[][2]);
|