| /* |
| This file is part of libmicrohttpd |
| Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff |
| |
| This library 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 library 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 library; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /** |
| * @file lib/action_from_response.c |
| * @brief implementation of #MHD_action_from_response() |
| * @author Christian Grothoff |
| */ |
| #include "internal.h" |
| #include "connection_call_handlers.h" |
| |
| |
| /** |
| * A response was given as the desired action for a @a request. |
| * Queue the response for the request. |
| * |
| * @param cls the `struct MHD_Response` |
| * @param request the request we are processing |
| * @return #MHD_SC_OK on success |
| */ |
| static enum MHD_StatusCode |
| response_action (void *cls, |
| struct MHD_Request *request) |
| { |
| struct MHD_Response *response = cls; |
| struct MHD_Daemon *daemon = request->daemon; |
| |
| /* If daemon was shut down in parallel, |
| * response will be aborted now or on later stage. */ |
| if (daemon->shutdown) |
| return MHD_SC_DAEMON_ALREADY_SHUTDOWN; |
| |
| #ifdef UPGRADE_SUPPORT |
| if ( (NULL != response->upgrade_handler) && |
| daemon->disallow_upgrade) |
| { |
| #ifdef HAVE_MESSAGES |
| MHD_DLOG (daemon, |
| MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED, |
| _ ( |
| "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n")); |
| #endif |
| return MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED; |
| } |
| #endif /* UPGRADE_SUPPORT */ |
| request->response = response; |
| #if defined(_MHD_HAVE_SENDFILE) |
| if ( (-1 == response->fd) |
| #if HTTPS_SUPPORT |
| || (NULL != daemon->tls_api) |
| #endif |
| ) |
| request->resp_sender = MHD_resp_sender_std; |
| else |
| request->resp_sender = MHD_resp_sender_sendfile; |
| #endif /* _MHD_HAVE_SENDFILE */ |
| |
| if ( (MHD_METHOD_HEAD == request->method) || |
| (MHD_HTTP_OK > response->status_code) || |
| (MHD_HTTP_NO_CONTENT == response->status_code) || |
| (MHD_HTTP_NOT_MODIFIED == response->status_code) ) |
| { |
| /* if this is a "HEAD" request, or a status code for |
| which a body is not allowed, pretend that we |
| have already sent the full message body. */ |
| request->response_write_position = response->total_size; |
| } |
| if ( (MHD_REQUEST_HEADERS_PROCESSED == request->state) && |
| ( (MHD_METHOD_POST == request->method) || |
| (MHD_METHOD_PUT == request->method) ) ) |
| { |
| /* response was queued "early", refuse to read body / footers or |
| further requests! */ |
| request->connection->read_closed = true; |
| request->state = MHD_REQUEST_FOOTERS_RECEIVED; |
| } |
| if (! request->in_idle) |
| (void) MHD_request_handle_idle_ (request); |
| return MHD_SC_OK; |
| } |
| |
| |
| /** |
| * Converts a @a response to an action. If @a consume |
| * is set, the reference to the @a response is consumed |
| * by the conversion. If @a consume is #MHD_NO, then |
| * the response can be converted to actions in the future. |
| * However, the @a response is frozen by this step and |
| * must no longer be modified (i.e. by setting headers). |
| * |
| * @param response response to convert, not NULL |
| * @param destroy_after_use should the response object be consumed? |
| * @return corresponding action, never returns NULL |
| * |
| * Implementation note: internally, this is largely just |
| * a cast (and possibly an RC increment operation), |
| * as a response *is* an action. As no memory is |
| * allocated, this operation cannot fail. |
| */ |
| _MHD_EXTERN const struct MHD_Action * |
| MHD_action_from_response (struct MHD_Response *response, |
| enum MHD_Bool destroy_after_use) |
| { |
| response->action.action = &response_action; |
| response->action.action_cls = response; |
| if (! destroy_after_use) |
| { |
| MHD_mutex_lock_chk_ (&response->mutex); |
| response->reference_count++; |
| MHD_mutex_unlock_chk_ (&response->mutex); |
| } |
| return &response->action; |
| } |
| |
| |
| /* end of action_from_response */ |