/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "array.h"
#include "istream.h"
#include "ostream-private.h"
#include "http-date.h"
#include "http-transfer.h"
#include "http-server-private.h"
struct http_server_response_payload {
};
/*
* Logging
*/
static inline void
static inline void
const char *format, ...)
{
i_debug("http-server: request %s; %u response: %s",
}
}
static inline void
static inline void
const char *format, ...)
{
i_error("http-server: request %s; %u response: %s",
}
/*
* Response
*/
struct http_server_response *
{
} else {
/* was already composing a response, but decided to
start a new one (would usually be a failure response)
*/
}
return resp;
}
{
}
{
/* mark presence of special headers */
switch (key[0]) {
case 'c': case 'C':
break;
case 'd': case 'D':
break;
case 't': case 'T':
break;
}
}
unsigned int status,
const char *reason)
{
/* free not called because pool is alloconly */
}
{
}
{
int ret;
if (ret < 0) {
i_error("i_stream_get_size(%s) failed: %s",
}
resp->payload_size = 0;
}
}
{
unsigned char *payload_data;
if (size == 0)
return;
}
struct http_server_response *resp,
const struct http_auth_challenge *chlng)
{
}
{
}
static void
{
}
{
}
{
}
{
}
static void
{
}
if (resp->payload_corked &&
}
}
static int
{
unsigned int iov_count, i;
if (http_server_connection_flush(conn) < 0)
return -1;
return -1;
}
if (ret > 0) {
bytes_left = ret;
for (i = 0; i < iov_count && bytes_left > 0; i++) {
bytes_left -= block_len;
}
if (i < iov_count) {
} else {
}
}
return 1;
}
static int
struct http_server_response **_resp,
{
int ret;
/* Discard any remaining incoming payload */
if (http_server_connection_discard_payload(conn) < 0)
return -1;
} else {
}
resp->payload_size = 0;
/* Wait for payload data to be written */
do {
"Preparing to send blocking payload");
"Sending blocking payload");
} else {
break;
}
break;
}
ret = 1;
break;
"Request aborted while sending blocking payload");
ret = -1;
break;
default:
ret = 0;
break;
}
/* callback may have messed with our pointer,
so unref using local variable */
if (!http_server_request_unref(&req))
/* Return status */
return ret;
}
{
int ret;
if (ret < 0)
else {
}
return ret;
}
{
int ret;
return ret < 0 ? -1 : 0;
}
{
"Aborted sending response payload");
}
static void
{
(void)http_server_connection_output(conn);
}
{
int ret = 0;
/* chunked ostream needs to write to the parent stream's buffer */
switch (res) {
/* finished sending */
if (!resp->payload_chunked &&
resp->payload_size) {
"Payload stream %s size changed unexpectedly",
"Payload read failure");
ret = -1;
} else {
ret = 1;
}
break;
/* input is blocking */
break;
/* output is blocking */
//http_server_response_debug(resp, "Partially sent payload");
break;
/* we're in the middle of sending a response, so the connection
will also have to be aborted */
"read(%s) failed: %s",
"Payload read failure");
ret = -1;
break;
/* failed to send response */
ret = -1;
break;
}
if (ret != 0) {
/* finished sending payload (or error) */
}
return ret < 0 ? -1 : 0;
}
{
/* create status line */
/* create special headers implicitly if not set explicitly using
http_server_response_add_header() */
if (!resp->have_hdr_date) {
}
}
if (resp->payload_chunked) {
if (!is_head) {
/* cannot use Transfer-Encoding */
/* connection close marks end of payload */
}
} else {
if (!resp->have_hdr_body_spec)
if (!is_head) {
}
}
} else {
/* send Content-Length if we have specified a payload,
even if it's 0 bytes. */
if (!resp->have_hdr_body_spec) {
resp->payload_size);
}
if (!is_head) {
}
}
/* RFC 7230, Section 3.3: Message Body
Responses to the HEAD request method (Section 4.3.2 of [RFC7231])
never include a message body because the associated response header
fields (e.g., Transfer-Encoding, Content-Length, etc.), if present,
indicate only what their values would have been if the request method
had been GET (Section 4.3.1 of [RFC7231]). 2xx (Successful) responses
to a CONNECT request method (Section 4.3.6 of [RFC7231]) switch to
tunnel mode instead of having a message body. All 1xx (Informational),
204 (No Content), and 304 (Not Modified) responses do not include a
message body. All other responses do include a message body, although
the body might be of zero length.
RFC 7230, Section 3.3.2: Content-Length
A server MUST NOT send a Content-Length header field in any 2xx
(Successful) response to a CONNECT request (Section 4.3.6 of [RFC7231]).
-> Create empty body if it is missing.
*/
if (!resp->have_hdr_body_spec)
}
if (!resp->have_hdr_connection) {
}
/* status line + implicit headers */
/* explicit headers */
/* end of header */
return -1;
}
if (resp->payload_blocking) {
/* blocking payload */
/* non-blocking payload */
if (http_server_response_send_more(resp) < 0)
return -1;
} else {
/* no payload to send */
}
return -1;
}
return 0;
}
{
int ret;
T_BEGIN {
} T_END;
return ret;
}
/*
* Payload output stream
*/
struct http_server_ostream {
};
static ssize_t
{
(struct http_server_ostream *)stream;
unsigned int i;
} else {
"HTTP connection broke while sending payload");
}
return -1;
}
ret = 0;
for (i = 0; i < iov_count; i++)
return ret;
}
bool close_parent ATTR_UNUSED)
{
(struct http_server_ostream *)stream;
return;
} else {
"HTTP connection broke while sending payload");
}
}
}
{
(struct http_server_ostream *)stream;
}
}
struct ostream *
bool blocking)
{
return resp->blocking_output;
}
{
}
{
}