diff options
Diffstat (limited to 'src/lib/action_from_response.c')
-rw-r--r-- | src/lib/action_from_response.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/lib/action_from_response.c b/src/lib/action_from_response.c new file mode 100644 index 00000000..3c13cf42 --- /dev/null +++ b/src/lib/action_from_response.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file lib/action_from_response.c | ||
22 | * @brief implementation of #MHD_action_from_response() | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "internal.h" | ||
26 | |||
27 | |||
28 | /** | ||
29 | * A response was given as the desired action for a @a request. | ||
30 | * Queue the response for the request. | ||
31 | * | ||
32 | * @param cls the `struct MHD_Response` | ||
33 | * @param request the request we are processing | ||
34 | */ | ||
35 | static void | ||
36 | response_action (void *cls, | ||
37 | struct MHD_Request *request) | ||
38 | { | ||
39 | struct MHD_Response *response = cls; | ||
40 | struct MHD_Daemon *daemon = response->daemon; | ||
41 | |||
42 | if (daemon->shutdown) | ||
43 | return MHD_YES; /* If daemon was shut down in parallel, | ||
44 | * response will be aborted now or on later stage. */ | ||
45 | |||
46 | #ifdef UPGRADE_SUPPORT | ||
47 | if ( (NULL != response->upgrade_handler) && | ||
48 | (0 == (daemon->options & MHD_ALLOW_UPGRADE)) ) | ||
49 | { | ||
50 | #ifdef HAVE_MESSAGES | ||
51 | MHD_DLOG (daemon, | ||
52 | _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n")); | ||
53 | #endif | ||
54 | return MHD_NO; | ||
55 | } | ||
56 | #endif /* UPGRADE_SUPPORT */ | ||
57 | request->response = response; | ||
58 | #if defined(_MHD_HAVE_SENDFILE) | ||
59 | if ( (-1 == response->fd) | ||
60 | #if HTTPS_SUPPORT | ||
61 | || (NULL != daemon->tls_api) | ||
62 | #endif | ||
63 | ) | ||
64 | request->resp_sender = MHD_resp_sender_std; | ||
65 | else | ||
66 | request->resp_sender = MHD_resp_sender_sendfile; | ||
67 | #endif /* _MHD_HAVE_SENDFILE */ | ||
68 | |||
69 | if ( ( (NULL != request->method) && | ||
70 | (MHD_str_equal_caseless_ (request->method, | ||
71 | MHD_HTTP_METHOD_HEAD)) ) || | ||
72 | (MHD_HTTP_OK > response->status_code) || | ||
73 | (MHD_HTTP_NO_CONTENT == response->status_code) || | ||
74 | (MHD_HTTP_NOT_MODIFIED == response->status_code) ) | ||
75 | { | ||
76 | /* if this is a "HEAD" request, or a status code for | ||
77 | which a body is not allowed, pretend that we | ||
78 | have already sent the full message body. */ | ||
79 | request->response_write_position = response->total_size; | ||
80 | } | ||
81 | if ( (MHD_REQUEST_HEADERS_PROCESSED == request->state) && | ||
82 | (NULL != connection->method) && | ||
83 | ( (MHD_str_equal_caseless_ (request->method, | ||
84 | MHD_HTTP_METHOD_POST)) || | ||
85 | (MHD_str_equal_caseless_ (request->method, | ||
86 | MHD_HTTP_METHOD_PUT))) ) | ||
87 | { | ||
88 | /* response was queued "early", refuse to read body / footers or | ||
89 | further requests! */ | ||
90 | connection->read_closed = true; | ||
91 | request->state = MHD_CONNECTION_FOOTERS_RECEIVED; | ||
92 | } | ||
93 | if (! request->in_idle) | ||
94 | (void) MHD_connection_handle_idle (connection); | ||
95 | } | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Converts a @a response to an action. If @a consume | ||
100 | * is set, the reference to the @a response is consumed | ||
101 | * by the conversion. If @a consume is #MHD_NO, then | ||
102 | * the response can be converted to actions in the future. | ||
103 | * However, the @a response is frozen by this step and | ||
104 | * must no longer be modified (i.e. by setting headers). | ||
105 | * | ||
106 | * @param response response to convert, not NULL | ||
107 | * @param destroy_after_use should the response object be consumed? | ||
108 | * @return corresponding action, never returns NULL | ||
109 | * | ||
110 | * Implementation note: internally, this is largely just | ||
111 | * a cast (and possibly an RC increment operation), | ||
112 | * as a response *is* an action. As no memory is | ||
113 | * allocated, this operation cannot fail. | ||
114 | */ | ||
115 | _MHD_EXTERN struct MHD_Action * | ||
116 | MHD_action_from_response (struct MHD_Response *response, | ||
117 | enum MHD_bool destroy_after_use) | ||
118 | { | ||
119 | response->action.action = &response_action; | ||
120 | response->action.action_cls = response; | ||
121 | if (! destroy_after_use) | ||
122 | { | ||
123 | MHD_mutex_lock_chk_ (&response->mutex); | ||
124 | response->reference_count++; | ||
125 | MHD_mutex_unlock_chk_ (&response->mutex); | ||
126 | } | ||
127 | return &response->action; | ||
128 | } | ||
129 | |||
130 | /* end of action_from_response */ | ||