/src/mhd2/src/mhd2/h2/h2_app_cb.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ |
2 | | /* |
3 | | This file is part of GNU libmicrohttpd. |
4 | | Copyright (C) 2025 Evgeny Grin (Karlson2k) |
5 | | |
6 | | GNU libmicrohttpd is free software; you can redistribute it and/or |
7 | | modify it under the terms of the GNU Lesser General Public |
8 | | License as published by the Free Software Foundation; either |
9 | | version 2.1 of the License, or (at your option) any later version. |
10 | | |
11 | | GNU libmicrohttpd is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | Lesser General Public License for more details. |
15 | | |
16 | | Alternatively, you can redistribute GNU libmicrohttpd and/or |
17 | | modify it under the terms of the GNU General Public License as |
18 | | published by the Free Software Foundation; either version 2 of |
19 | | the License, or (at your option) any later version, together |
20 | | with the eCos exception, as follows: |
21 | | |
22 | | As a special exception, if other files instantiate templates or |
23 | | use macros or inline functions from this file, or you compile this |
24 | | file and link it with other works to produce a work based on this |
25 | | file, this file does not by itself cause the resulting work to be |
26 | | covered by the GNU General Public License. However the source code |
27 | | for this file must still be made available in accordance with |
28 | | section (3) of the GNU General Public License v2. |
29 | | |
30 | | This exception does not invalidate any other reasons why a work |
31 | | based on this file might be covered by the GNU General Public |
32 | | License. |
33 | | |
34 | | You should have received copies of the GNU Lesser General Public |
35 | | License and the GNU General Public License along with this library; |
36 | | if not, see <https://www.gnu.org/licenses/>. |
37 | | */ |
38 | | |
39 | | /** |
40 | | * @file src/mhd2/h2/h2_app_cb.c |
41 | | * @brief Implementation of HTTP/2 functions for calling application callbacks |
42 | | * @author Karlson2k (Evgeny Grin) |
43 | | */ |
44 | | |
45 | | |
46 | | #include "mhd_sys_options.h" |
47 | | |
48 | | #include "sys_bool_type.h" |
49 | | #include "sys_base_types.h" |
50 | | |
51 | | #include "mhd_assert.h" |
52 | | #include "mhd_unreachable.h" |
53 | | |
54 | | #include "mhd_str_types.h" |
55 | | |
56 | | #include "mhd_daemon.h" |
57 | | #include "mhd_connection.h" |
58 | | #include "h2_conn_data.h" |
59 | | #include "h2_stream_data.h" |
60 | | |
61 | | #include "mhd_panic.h" |
62 | | #include "daemon_logger.h" |
63 | | |
64 | | #include "response_destroy.h" |
65 | | |
66 | | #include "h2_req_items_funcs.h" |
67 | | #include "h2_conn_streams.h" |
68 | | |
69 | | #include "h2_app_cb.h" |
70 | | |
71 | | |
72 | | MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool |
73 | | mhd_h2_stream_cb_early_uri (struct mhd_H2Stream *restrict s) |
74 | 0 | { |
75 | 0 | mhd_assert (mhd_H2_REQ_STAGE_HEADERS_DECODING == s->req.stage); |
76 | 0 | mhd_assert (mhd_HTTP_METHOD_NO_METHOD != s->req.method); |
77 | 0 | mhd_assert (mhd_h2_items_debug_get_streamid (s->c->h2.mem.req_ib) |
78 | 0 | == s->stream_id); |
79 | 0 | mhd_assert (mhd_H2_REQ_ITEM_POS_INVALID != s->req.pos_path); |
80 | |
|
81 | 0 | if (NULL != s->c->daemon->req_cfg.uri_cb.cb) |
82 | 0 | { |
83 | 0 | struct MHD_EarlyUriCbData req_data; |
84 | 0 | bool res; |
85 | |
|
86 | 0 | req_data.request = (struct MHD_Request *) (void*) &(s->req); |
87 | 0 | res = mhd_h2_items_get_item_value (s->c->h2.mem.req_ib, |
88 | 0 | s->req.pos_path, |
89 | 0 | &(req_data.full_uri)); |
90 | 0 | mhd_assert (res); |
91 | 0 | (void) res; |
92 | |
|
93 | 0 | if (s->c->h2.state.top_proc_stream_id < s->stream_id) |
94 | 0 | s->c->h2.state.top_proc_stream_id = s->stream_id; |
95 | 0 | s->req.app_seen = true; |
96 | |
|
97 | 0 | s->c->daemon->req_cfg.uri_cb.cb (s->c->daemon->req_cfg.uri_cb.cls, |
98 | 0 | &req_data, |
99 | 0 | &(s->req.app_context)); |
100 | 0 | } |
101 | |
|
102 | 0 | return true; |
103 | 0 | } |
104 | | |
105 | | |
106 | | MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool |
107 | | mhd_h2_stream_cb_request (struct mhd_H2Stream *restrict s) |
108 | 0 | { |
109 | 0 | struct MHD_Connection *restrict c = s->c; |
110 | 0 | struct MHD_Daemon *restrict d = c->daemon; |
111 | 0 | struct MHD_String path; |
112 | 0 | const struct MHD_Action *a; |
113 | |
|
114 | 0 | mhd_assert (mhd_C_IS_HTTP2 (c)); |
115 | 0 | mhd_assert (mhd_H2_REQ_STAGE_HEADERS_PROCESSING == s->req.stage); |
116 | 0 | mhd_assert (mhd_HTTP_METHOD_NO_METHOD != s->req.method); |
117 | 0 | mhd_assert (mhd_h2_items_debug_get_streamid (s->c->h2.mem.req_ib) |
118 | 0 | == s->stream_id); |
119 | 0 | mhd_assert (mhd_H2_REQ_ITEM_POS_INVALID != s->req.pos_path); |
120 | |
|
121 | 0 | mhd_assert (NULL == s->rpl.response); |
122 | |
|
123 | 0 | if (mhd_ACTION_NO_ACTION != s->req.app_act.head_act.act) |
124 | 0 | MHD_PANIC ("MHD_Action has been set already"); |
125 | |
|
126 | 0 | if (1) |
127 | 0 | { |
128 | 0 | bool res = |
129 | 0 | mhd_h2_items_get_item_value (s->c->h2.mem.req_ib, |
130 | 0 | s->req.pos_path, |
131 | 0 | &(path)); |
132 | 0 | mhd_assert (res); |
133 | 0 | (void) res; |
134 | 0 | } |
135 | |
|
136 | 0 | if (s->c->h2.state.top_proc_stream_id < s->stream_id) |
137 | 0 | s->c->h2.state.top_proc_stream_id = s->stream_id; |
138 | 0 | s->req.app_seen = true; |
139 | |
|
140 | 0 | a = d->req_cfg.cb (d->req_cfg.cb_cls, |
141 | 0 | (struct MHD_Request *) (void*) &(s->req), |
142 | 0 | &path, |
143 | 0 | (enum MHD_HTTP_Method) s->req.method, |
144 | 0 | s->req.cntn_size); |
145 | |
|
146 | 0 | if ((NULL != a) |
147 | 0 | && (((&(s->req.app_act.head_act) != a)) |
148 | 0 | || ! mhd_ACTION_IS_VALID (s->req.app_act.head_act.act))) |
149 | 0 | { |
150 | 0 | mhd_LOG_MSG (d, MHD_SC_ACTION_INVALID, \ |
151 | 0 | "Provided action is not a correct action generated " \ |
152 | 0 | "for the current request."); |
153 | | /* Perform cleanup of the created but now unused action */ |
154 | 0 | switch (s->req.app_act.head_act.act) |
155 | 0 | { |
156 | 0 | case mhd_ACTION_RESPONSE: |
157 | 0 | mhd_assert (NULL != s->req.app_act.head_act.data.response); |
158 | 0 | mhd_response_dec_use_count (s->req.app_act.head_act.data.response); |
159 | 0 | break; |
160 | 0 | case mhd_ACTION_UPLOAD: |
161 | 0 | case mhd_ACTION_SUSPEND: |
162 | | /* No cleanup needed */ |
163 | 0 | break; |
164 | 0 | #ifdef MHD_SUPPORT_POST_PARSER |
165 | 0 | case mhd_ACTION_POST_PARSE: |
166 | | /* No cleanup needed */ |
167 | 0 | break; |
168 | 0 | #endif /* MHD_SUPPORT_POST_PARSER */ |
169 | 0 | #ifdef MHD_SUPPORT_UPGRADE |
170 | 0 | case mhd_ACTION_UPGRADE: |
171 | | /* No cleanup needed */ |
172 | 0 | break; |
173 | 0 | #endif /* MHD_SUPPORT_UPGRADE */ |
174 | 0 | case mhd_ACTION_ABORT: |
175 | 0 | mhd_UNREACHABLE (); |
176 | 0 | break; |
177 | 0 | case mhd_ACTION_NO_ACTION: |
178 | 0 | default: |
179 | 0 | break; |
180 | 0 | } |
181 | 0 | a = NULL; |
182 | 0 | } |
183 | 0 | if (NULL == a) |
184 | 0 | s->req.app_act.head_act.act = mhd_ACTION_ABORT; |
185 | |
|
186 | 0 | switch (s->req.app_act.head_act.act) |
187 | 0 | { |
188 | 0 | case mhd_ACTION_RESPONSE: |
189 | 0 | s->rpl.response = s->req.app_act.head_act.data.response; |
190 | 0 | return true; |
191 | | #if 0 |
192 | | case mhd_ACTION_UPLOAD: |
193 | | if (0 != s->req.cntn_size) |
194 | | { |
195 | | if (! check_and_alloc_buf_for_upload_processing (c)) |
196 | | return true; |
197 | | c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; |
198 | | return (0 != c->read_buffer_offset); |
199 | | } |
200 | | c->stage = mhd_HTTP_STAGE_FULL_REQ_RECEIVED; |
201 | | return true; |
202 | | #ifdef MHD_SUPPORT_POST_PARSER |
203 | | case mhd_ACTION_POST_PARSE: |
204 | | if (0 == s->req.cntn.cntn_size) |
205 | | { |
206 | | s->req.u_proc.post.parse_result = MHD_POST_PARSE_RES_REQUEST_EMPTY; |
207 | | c->stage = mhd_HTTP_STAGE_FULL_REQ_RECEIVED; |
208 | | return true; |
209 | | } |
210 | | if (! mhd_stream_prepare_for_post_parse (c)) |
211 | | { |
212 | | mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVED < c->stage); |
213 | | return true; |
214 | | } |
215 | | if (need_100_continue (c)) |
216 | | { |
217 | | c->stage = mhd_HTTP_STAGE_CONTINUE_SENDING; |
218 | | return true; |
219 | | } |
220 | | c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; |
221 | | return true; |
222 | | #endif /* MHD_SUPPORT_POST_PARSER */ |
223 | | case mhd_ACTION_SUSPEND: |
224 | | c->suspended = true; |
225 | | #ifdef MHD_USE_TRACE_SUSPEND_RESUME |
226 | | fprintf (stderr, |
227 | | "%%%%%% Suspending connection, FD: %2llu\n", |
228 | | (unsigned long long) c->sk.fd); |
229 | | #endif /* MHD_USE_TRACE_SUSPEND_RESUME */ |
230 | | s->req.app_act.head_act.act = mhd_ACTION_NO_ACTION; |
231 | | return false; |
232 | | #ifdef MHD_SUPPORT_UPGRADE |
233 | | case mhd_ACTION_UPGRADE: |
234 | | mhd_assert (0 == s->req.cntn.cntn_size); |
235 | | c->stage = mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING; |
236 | | return false; |
237 | | #endif /* MHD_SUPPORT_UPGRADE */ |
238 | | case mhd_ACTION_ABORT: |
239 | | mhd_conn_start_closing_app_abort (c); |
240 | | return true; |
241 | | case mhd_ACTION_NO_ACTION: |
242 | | default: |
243 | | mhd_assert (0 && "Impossible value"); |
244 | | mhd_UNREACHABLE (); |
245 | | break; |
246 | | #endif |
247 | 0 | } |
248 | | |
249 | 0 | return mhd_h2_stream_abort (s, |
250 | 0 | mhd_H2_ERR_INTERNAL_ERROR); |
251 | 0 | } |