bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "lib.h"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch#include "ioloop.h"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch#include "ostream.h"
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch#include "istream-private.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "http-server-private.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch/*
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch * Logging
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch */
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschstatic inline void
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschhttp_server_request_debug(struct http_server_request *req,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch const char *format, ...) ATTR_FORMAT(2, 3);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschstatic inline void
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschhttp_server_request_debug(struct http_server_request *req,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch const char *format, ...)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch struct http_server *server = req->server;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch va_list args;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch if (server->set.debug) {
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch va_start(args, format);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch i_debug("http-server: request %s: %s",
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch http_server_request_label(req),
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch t_strdup_vprintf(format, args));
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch va_end(args);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch }
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic inline void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschhttp_server_request_error(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch const char *format, ...) ATTR_FORMAT(2, 3);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic inline void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschhttp_server_request_error(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch const char *format, ...)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_list args;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_start(args, format);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_error("http-server: request %s: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_label(req),
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch t_strdup_vprintf(format, args));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_end(args);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic inline void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschhttp_server_request_client_error(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch const char *format, ...) ATTR_FORMAT(2, 3);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic inline void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschhttp_server_request_client_error(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch const char *format, ...)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_list args;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_start(args, format);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_info("http-server: request %s: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_label(req),
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch t_strdup_vprintf(format, args));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch va_end(args);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch/*
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch * Request
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch */
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstruct http_server_request *
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschhttp_server_request_new(struct http_server_connection *conn)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch static unsigned int id_counter = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch pool_t pool;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_request *req;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
45324f1eafa565dbc65e4dd335de9507dead55e6Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"http_server_request", 4096);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req = p_new(pool, struct http_server_request, 1);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->pool = pool;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->refcount = 1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->conn = conn;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->server = conn->server;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch req->id = ++id_counter;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
833bed942977673526c72e79bccc09314fc57104Phil Carmody http_server_connection_add_request(conn, req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return req;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_ref(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
e9228a3918aa0243eff4aae1ff5462bd3198417fTimo Sirainen i_assert(req->refcount > 0);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->refcount++;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainenbool http_server_request_unref(struct http_server_request **_req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_request *req = *_req;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_connection *conn = req->conn;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(req->refcount > 0);
903f0b38884375179cea63b9d0821e295c38764aTimo Sirainen
903f0b38884375179cea63b9d0821e295c38764aTimo Sirainen *_req = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (--req->refcount > 0)
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen return TRUE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch http_server_request_debug(req, "Free");
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
833bed942977673526c72e79bccc09314fc57104Phil Carmody if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
833bed942977673526c72e79bccc09314fc57104Phil Carmody http_server_connection_remove_request(conn, req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (req->destroy_callback != NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->destroy_callback(req->destroy_context);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->destroy_callback = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (req->response != NULL)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_response_free(req->response);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch pool_unref(&req->pool);
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen return FALSE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Boschvoid http_server_request_connection_close(struct http_server_request *req,
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch bool close)
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch{
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE);
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch req->connection_close = close;
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch}
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainenvoid http_server_request_destroy(struct http_server_request **_req)
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen{
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen struct http_server_request *req = *_req;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch struct http_server *server = req->server;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch http_server_request_debug(req, "Destroy");
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* just make sure the request ends in a proper state */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (server->ioloop != NULL)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch io_loop_stop(server->ioloop);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen if (req->delay_destroy) {
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen req->destroy_pending = TRUE;
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen } else if (req->destroy_callback != NULL) {
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch void (*callback)(void *) = req->destroy_callback;
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen req->destroy_callback = NULL;
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch callback(req->destroy_context);
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen }
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen http_server_request_unref(_req);
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen}
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
582b93659812592a27babdb65c6cb4c37042ab00Aki Tuomi#undef http_server_request_set_destroy_callback
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_set_destroy_callback(struct http_server_request *req,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch void (*callback)(void *),
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch void *context)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->destroy_callback = callback;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->destroy_context = context;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Boschvoid http_server_request_abort(struct http_server_request **_req,
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch const char *reason)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_request *req = *_req;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_connection *conn = req->conn;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch if (req->state >= HTTP_SERVER_REQUEST_STATE_FINISHED)
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch return;
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch http_server_request_debug(req, "Abort");
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch req->conn = NULL;
833bed942977673526c72e79bccc09314fc57104Phil Carmody if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (conn != NULL) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch http_server_connection_remove_request(conn, req);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (!conn->closed) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* send best-effort response if appropriate */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (!conn->output_locked &&
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch req->state >= HTTP_SERVER_REQUEST_STATE_PROCESSING &&
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch static const char *response =
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch "HTTP/1.1 500 Internal Server Error\r\n"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch "Content-Length: 0\r\n"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch "\r\n";
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch (void)o_stream_send(conn->conn.output,
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch response, strlen(response));
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* close the connection */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch http_server_connection_close(&conn, reason);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (req->response != NULL &&
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch !req->response->payload_blocking) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_response_free(req->response);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch req->response = NULL;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
91a482473f200152d6713181c0e36f7a4f03ef6dTimo Sirainen http_server_request_destroy(_req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschconst struct http_request *
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschhttp_server_request_get(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return &req->req;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschpool_t
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschhttp_server_request_get_pool(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return req->pool;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainenstruct http_server_response *
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainenhttp_server_request_get_response(struct http_server_request *req)
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen{
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen return req->response;
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen}
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschint http_server_request_get_auth(struct http_server_request *req,
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch struct http_auth_credentials *credentials)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch const char *auth;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch auth = http_request_header_get(&req->req, "Authorization");
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (auth == NULL)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return 0;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (http_auth_parse_credentials
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch ((const unsigned char *)auth, strlen(auth), credentials) < 0)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return -1;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return 1;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch}
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
93ed69606237a08623f8294c060fa148880058f8Timo Sirainenbool http_server_request_is_finished(struct http_server_request *req)
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen{
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen return req->response != NULL ||
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen req->state == HTTP_SERVER_REQUEST_STATE_ABORTED;
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen}
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Boschbool http_server_request_is_complete(struct http_server_request *req)
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch{
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch return (req->failed || req->conn->input_broken ||
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch (req->next != NULL && !http_server_request_is_new(req->next)) ||
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch !http_server_connection_pending_payload(req->conn));
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch}
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_halt_payload(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->payload_halted = TRUE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_continue_payload(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->payload_halted = FALSE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (req->req.expect_100_continue && !req->sent_100_continue)
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch http_server_connection_trigger_responses(req->conn);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_ready_to_respond(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch http_server_request_debug(req, "Ready to respond");
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND;
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch http_server_connection_trigger_responses(req->conn);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_submit_response(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_connection *conn = req->conn;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(conn != NULL && req->response != NULL && req->response->submitted);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_ref(req);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (conn->payload_handler != NULL && conn->payload_handler->req == req)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_payload_handler_destroy(&conn->payload_handler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch switch (req->state) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch case HTTP_SERVER_REQUEST_STATE_NEW:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch case HTTP_SERVER_REQUEST_STATE_QUEUED:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch case HTTP_SERVER_REQUEST_STATE_PAYLOAD_IN:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch case HTTP_SERVER_REQUEST_STATE_PROCESSING:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (!http_server_request_is_complete(req)) {
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch http_server_request_debug(req, "Not ready to respond");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch break;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_request_ready_to_respond(req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch break;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch case HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND:
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_connection_trigger_responses(req->conn);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch break;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch case HTTP_SERVER_REQUEST_STATE_ABORTED:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch break;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch default:
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_unreached();
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_unref(&req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid http_server_request_finished(struct http_server_request *req)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_connection *conn = req->conn;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_response *resp = req->response;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_tunnel_callback_t tunnel_callback = resp->tunnel_callback;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch void *tunnel_context = resp->tunnel_context;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch http_server_request_debug(req, "Finished");
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(req->state < HTTP_SERVER_REQUEST_STATE_FINISHED);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch req->state = HTTP_SERVER_REQUEST_STATE_FINISHED;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
833bed942977673526c72e79bccc09314fc57104Phil Carmody http_server_connection_remove_request(conn, req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch conn->stats.response_count++;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch if (tunnel_callback == NULL) {
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch if (req->connection_close) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_connection_close(&conn,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch t_strdup_printf("Server closed connection: %u %s",
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch resp->status, resp->reason));
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch http_server_request_destroy(&req);
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch return;
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch } else if (req->conn->input_broken) {
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch http_server_connection_close(&conn,
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch "Connection input is broken");
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch http_server_request_destroy(&req);
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch return;
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch } else if (req->req.connection_close) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_connection_close(&conn,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "Client requested connection close");
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch http_server_request_destroy(&req);
e2a5de324df523512c42086d8422e4e41adf2c28Stephan Bosch return;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen http_server_request_destroy(&req);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (tunnel_callback != NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch http_server_connection_tunnel(&conn, tunnel_callback, tunnel_context);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch http_server_connection_trigger_responses(conn);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Boschstatic struct http_server_response *
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschhttp_server_request_create_fail_response(struct http_server_request *req,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch unsigned int status, const char *reason, const char *text)
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch ATTR_NULL(4)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct http_server_response *resp;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
b37e11d37fb1ebf50511eef5d9d96d1205818458Stephan Bosch req->failed = TRUE;
b37e11d37fb1ebf50511eef5d9d96d1205818458Stephan Bosch
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch i_assert(status / 100 != 1 && status != 204 && status != 304);
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch resp = http_server_response_create(req, status, reason);
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch if (!http_request_method_is(&req->req, "HEAD")) {
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch http_server_response_add_header
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch (resp, "Content-Type", "text/plain; charset=utf-8");
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch if (text == NULL)
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch text = reason;
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch text = t_strconcat(text, "\r\n", NULL);
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch http_server_response_set_payload_data
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch (resp, (const unsigned char *)text, strlen(text));
355a3cf3f2fad0293614cb3ed533629d52967f27Stephan Bosch }
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return resp;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch}
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschstatic void
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschhttp_server_request_fail_full(struct http_server_request *req,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch unsigned int status, const char *reason, const char *text)
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch ATTR_NULL(4)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch struct http_server_response *resp;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch req->failed = TRUE;
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch resp = http_server_request_create_fail_response(req,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch status, reason, text);
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch http_server_response_submit(resp);
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch if (req->conn->input_broken)
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch req->connection_close = TRUE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainenvoid http_server_request_fail(struct http_server_request *req,
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen unsigned int status, const char *reason)
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen{
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch http_server_request_fail_full(req, status, reason, NULL);
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen}
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainenvoid http_server_request_fail_close(struct http_server_request *req,
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen unsigned int status, const char *reason)
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen{
a5886aec87fbfd767a110e6168ce96411acfe798Stephan Bosch http_server_request_connection_close(req, TRUE);
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch http_server_request_fail_full(req, status, reason, NULL);
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch}
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Boschvoid http_server_request_fail_text(struct http_server_request *req,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch unsigned int status, const char *reason, const char *format, ...)
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch{
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch va_list args;
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch va_start(args, format);
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch http_server_request_fail_full(req, status, reason,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch t_strdup_vprintf(format, args));
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch va_end(args);
95e0b82fdff1bb511067d703bb8b67c22f242c38Timo Sirainen}
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschvoid http_server_request_fail_auth(struct http_server_request *req,
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch const char *reason, const struct http_auth_challenge *chlng)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch struct http_server_response *resp;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch req->failed = TRUE;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (reason == NULL)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch reason = "Unauthenticated";
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch resp = http_server_request_create_fail_response(req,
001b7ca6a75e7052511420f9394ed7a7cf008f4aStephan Bosch 401, reason, reason);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch http_server_response_add_auth(resp, chlng);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch http_server_response_submit(resp);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch}
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschvoid http_server_request_fail_auth_basic(struct http_server_request *req,
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch const char *reason, const char *realm)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch struct http_auth_challenge chlng;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch http_auth_basic_challenge_init(&chlng, realm);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch http_server_request_fail_auth(req, reason, &chlng);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch}
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch/*
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch * Payload input stream
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch */
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstruct http_server_istream {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct istream_private istream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_request *req;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch ssize_t read_status;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch};
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstatic void
038c2831447440bf0bef89b43dd0968afc298abcStephan Boschhttp_server_istream_switch_ioloop_to(struct istream_private *stream,
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch struct ioloop *ioloop)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch{
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_istream *hsristream =
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch (struct http_server_istream *)stream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if (hsristream->istream.istream.blocking)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch return;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch i_assert(ioloop == current_ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_switch_ioloop(hsristream->req->conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch}
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstatic void
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschhttp_server_istream_read_any(struct http_server_istream *hsristream)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch{
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct istream_private *stream = &hsristream->istream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server *server = hsristream->req->server;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch ssize_t ret;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if ((ret=i_stream_read_copy_from_parent
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch (&stream->istream)) > 0) {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->read_status = ret;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_loop_stop(server->ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch}
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstatic ssize_t
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschhttp_server_istream_read(struct istream_private *stream)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch{
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_istream *hsristream =
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch (struct http_server_istream *)stream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_request *req = hsristream->req;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server *server;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_connection *conn;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch bool blocking = stream->istream.blocking;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch ssize_t ret;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if (req == NULL) {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch /* request already gone (we shouldn't get here) */
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch stream->istream.stream_errno = EINVAL;
e173fd380024b495c953dd4589f4908fa601eb8eTimo Sirainen return -1;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch i_stream_seek(stream->parent, stream->parent_start_offset +
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch stream->istream.v_offset);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch server = hsristream->req->server;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch conn = hsristream->req->conn;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch ret = i_stream_read_copy_from_parent(&stream->istream);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if (ret == 0 && blocking) {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct ioloop *prev_ioloop = current_ioloop;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct io *io;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_ref(conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_request_ref(req);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch i_assert(server->ioloop == NULL);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch server->ioloop = io_loop_create();
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_switch_ioloop(conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if (blocking && req->req.expect_100_continue &&
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch !req->sent_100_continue)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_trigger_responses(conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->read_status = 0;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io = io_add_istream(&stream->istream,
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_istream_read_any, hsristream);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch while (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED &&
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->read_status == 0) {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_loop_run(server->ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_remove(&io);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_loop_set_current(prev_ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_switch_ioloop(conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_loop_set_current(server->ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch io_loop_destroy(&server->ioloop);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch ret = hsristream->read_status;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
903f0b38884375179cea63b9d0821e295c38764aTimo Sirainen if (!http_server_request_unref(&req))
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->req = NULL;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch http_server_connection_unref(&conn);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch return ret;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch}
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstatic void
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschhttp_server_istream_destroy(struct iostream_private *stream)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch{
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_istream *hsristream =
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch (struct http_server_istream *)stream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch uoff_t v_offset;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch v_offset = hsristream->istream.parent_start_offset +
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.istream.v_offset;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch if (hsristream->istream.parent->seekable ||
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch v_offset > hsristream->istream.parent->v_offset) {
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch /* get to same position in parent stream */
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch i_stream_seek(hsristream->istream.parent, v_offset);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch}
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschstruct istream *
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Boschhttp_server_request_get_payload_input(struct http_server_request *req,
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch bool blocking)
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch{
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct http_server_istream *hsristream;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch struct istream *payload = req->req.payload;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch i_assert(req->payload_input == NULL);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream = i_new(struct http_server_istream, 1);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->req = req;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.max_buffer_size =
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch payload->real_stream->max_buffer_size;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.stream_size_passthrough = TRUE;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.read = http_server_istream_read;
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch hsristream->istream.switch_ioloop_to = http_server_istream_switch_ioloop_to;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.iostream.destroy = http_server_istream_destroy;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.istream.readable_fd = FALSE;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.istream.blocking = blocking;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch hsristream->istream.istream.seekable = FALSE;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch req->payload_input = i_stream_create
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen (&hsristream->istream, payload, i_stream_get_fd(payload), 0);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch i_stream_unref(&req->req.payload);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch return req->payload_input;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch/*
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch * Payload handling
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch */
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschhttp_server_payload_handler_init(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler ,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_request *req)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(conn->payload_handler == NULL);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(conn->in_req_callback);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch conn->payload_handler = handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->req = req;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid http_server_payload_handler_destroy(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler **_handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler = *_handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = handler->req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (handler->in_callback) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch /* don't destroy handler while in callback */
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch return;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch *_handler = NULL;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(conn->payload_handler == NULL);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (handler->destroy != NULL)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->destroy(handler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid http_server_payload_handler_switch_ioloop(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (handler->switch_ioloop != NULL)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->switch_ioloop(handler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch/* pump-based */
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstruct http_server_payload_handler_pump {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct iostream_pump *pump;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void (*callback)(void *);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void *context;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch};
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschpayload_handler_pump_destroy(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_pump *phandler =
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (struct http_server_payload_handler_pump *)handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch iostream_pump_unref(&phandler->pump);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschpayload_handler_pump_switch_ioloop(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_pump *phandler =
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (struct http_server_payload_handler_pump *)handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch iostream_pump_switch_ioloop(phandler->pump);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
39435f00a35a276d329283179b3e7e0351482939Timo Sirainenpayload_handler_pump_callback(enum iostream_pump_status status,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_pump *phandler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler = &phandler->handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_request *req = handler->req;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct istream *input = iostream_pump_get_input(phandler->pump);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct ostream *output = iostream_pump_get_output(phandler->pump);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen switch (status) {
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen case IOSTREAM_PUMP_STATUS_INPUT_EOF:
1bc075e2e4ed422f9590c95c3ae223422b97ce6aTimo Sirainen if (!i_stream_read_eof(conn->incoming_payload)) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 413, "Payload Too Large");
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch } else {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch unsigned int old_refcount = req->refcount;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->in_callback = TRUE;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->callback(phandler->context);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch req->callback_refcount += req->refcount - old_refcount;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->in_callback = FALSE;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(req->callback_refcount > 0 ||
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (req->response != NULL && req->response->submitted));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen break;
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen case IOSTREAM_PUMP_STATUS_INPUT_ERROR:
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_client_error(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch "iostream_pump: read(%s) failed: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_get_name(input),
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_get_error(input));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 400, "Bad Request");
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen break;
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen case IOSTREAM_PUMP_STATUS_OUTPUT_ERROR:
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (output->stream_errno != 0) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_error(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch "iostream_pump: write(%s) failed: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch o_stream_get_name(output),
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch o_stream_get_error(output));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 500, "Internal Server Error");
39435f00a35a276d329283179b3e7e0351482939Timo Sirainen break;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (conn->payload_handler != NULL)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_payload_handler_destroy(&conn->payload_handler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch#undef http_server_request_forward_payload
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid http_server_request_forward_payload(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct ostream *output, uoff_t max_size,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void (*callback)(void *), void *context)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct istream *input = conn->incoming_payload;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_pump *phandler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch uoff_t payload_size;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch int ret;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(req->req.payload != NULL);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (max_size == (uoff_t)-1) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_ref(input);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch } else {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if ((ret = i_stream_get_size(input, TRUE, &payload_size)) != 0) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (ret < 0) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_error(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch "i_stream_get_size(%s) failed: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_get_name(input), i_stream_get_error(input));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 500, "Internal Server Error");
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch return;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (payload_size > max_size) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 413, "Payload Too Large");
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch return;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch input = i_stream_create_limit(input, max_size);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler = p_new(req->pool, struct http_server_payload_handler_pump, 1);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_payload_handler_init(&phandler->handler, req);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->handler.switch_ioloop = payload_handler_pump_switch_ioloop;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->handler.destroy = payload_handler_pump_destroy;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->callback = callback;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->context = context;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch phandler->pump = iostream_pump_create(input, output);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch iostream_pump_set_completion_callback(phandler->pump,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch payload_handler_pump_callback, phandler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch iostream_pump_start(phandler->pump);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_unref(&input);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch#undef http_server_request_buffer_payload
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid http_server_request_buffer_payload(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch buffer_t *buffer, uoff_t max_size,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void (*callback)(void *), void *context)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct ostream *output;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch output = o_stream_create_buffer(buffer);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_forward_payload(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch output, max_size, callback, context);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch o_stream_unref(&output);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch/* raw */
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstruct http_server_payload_handler_raw {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct io *io;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void (*callback)(void *context);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void *context;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch};
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschpayload_handler_raw_destroy(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_raw *rhandler =
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (struct http_server_payload_handler_raw *)handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch io_remove(&rhandler->io);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschpayload_handler_raw_switch_ioloop(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_raw *rhandler =
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (struct http_server_payload_handler_raw *)handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->io = io_loop_move_io(&rhandler->io);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschstatic void
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschpayload_handler_raw_input(
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_raw *rhandler)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler *handler = &rhandler->handler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_request *req = handler->req;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct istream *input = conn->incoming_payload;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch unsigned int old_refcount = req->refcount;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->in_callback = TRUE;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->callback(rhandler->context);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch req->callback_refcount += req->refcount - old_refcount;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch handler->in_callback = FALSE;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (input != NULL && input->stream_errno != 0) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (req->response == NULL) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_client_error(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch "read(%s) failed: %s",
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_get_name(input),
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_get_error(input));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_request_fail_close(req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch 400, "Bad Request");
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch } else if (input == NULL ||
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch !i_stream_have_bytes_left(input)) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_assert(req->callback_refcount > 0 ||
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch (req->response != NULL && req->response->submitted));
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch } else {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch return;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (conn->payload_handler != NULL)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_payload_handler_destroy(&conn->payload_handler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch#undef http_server_request_handle_payload
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid http_server_request_handle_payload(struct http_server_request *req,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void (*callback)(void *context), void *context)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_payload_handler_raw *rhandler;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct http_server_connection *conn = req->conn;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler = p_new(req->pool, struct http_server_payload_handler_raw, 1);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch http_server_payload_handler_init(&rhandler->handler, req);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->handler.switch_ioloop = payload_handler_raw_switch_ioloop;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->handler.destroy = payload_handler_raw_destroy;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->callback = callback;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->context = context;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch rhandler->io = io_add_istream(conn->incoming_payload,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch payload_handler_raw_input, rhandler);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch i_stream_set_input_pending(conn->incoming_payload, TRUE);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}