/src/mhd2/src/mhd2/upgrade_proc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | This file is part of GNU libmicrohttpd |
3 | | Copyright (C) 2024 Evgeny Grin (Karlson2k) |
4 | | |
5 | | GNU libmicrohttpd 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 | | GNU libmicrohttpd 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 | | /** |
22 | | * @file src/mhd2/upgrade_proc.c |
23 | | * @brief The implementation of functions for processing data for HTTP Upgrade |
24 | | * @author Karlson2k (Evgeny Grin) |
25 | | */ |
26 | | |
27 | | |
28 | | #include "mhd_sys_options.h" |
29 | | |
30 | | #include "upgrade_proc.h" |
31 | | |
32 | | #include "sys_base_types.h" |
33 | | |
34 | | #include "mhd_locks.h" |
35 | | |
36 | | #include "mhd_action.h" |
37 | | #include "mhd_connection.h" |
38 | | #include "mhd_daemon.h" |
39 | | #include "mhd_upgrade.h" |
40 | | |
41 | | #include "daemon_funcs.h" |
42 | | #include "stream_funcs.h" |
43 | | #include "daemon_logger.h" |
44 | | |
45 | | #include "mhd_public_api.h" |
46 | | |
47 | | |
48 | | MHD_INTERNAL |
49 | | MHD_FN_PAR_NONNULL_ (1) bool |
50 | | mhd_upgrade_try_start_upgrading (struct MHD_Connection *restrict c) |
51 | 0 | { |
52 | 0 | mhd_assert (mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING == c->stage); |
53 | 0 | mhd_assert ((mhd_ACTION_UPGRADE == c->rq.app_act.head_act.act) || |
54 | 0 | (mhd_UPLOAD_ACTION_UPGRADE == c->rq.app_act.upl_act.act)); |
55 | 0 | mhd_assert (NULL != c->write_buffer); |
56 | 0 | mhd_assert ((0 != c->read_buffer_offset) || (NULL == c->read_buffer)); |
57 | 0 | mhd_assert (NULL == c->upgr.c); |
58 | |
|
59 | 0 | if (c->write_buffer_append_offset != c->write_buffer_send_offset) |
60 | 0 | return false; |
61 | | |
62 | 0 | c->stage = mhd_HTTP_STAGE_UPGRADING; |
63 | |
|
64 | 0 | return true; |
65 | 0 | } |
66 | | |
67 | | |
68 | | MHD_INTERNAL |
69 | | MHD_FN_PAR_NONNULL_ (1) bool |
70 | | mhd_upgrade_finish_switch_to_upgraded (struct MHD_Connection *restrict c) |
71 | 0 | { |
72 | 0 | struct mhd_UpgradeActionData *pupgr_data; |
73 | 0 | mhd_assert (mhd_HTTP_STAGE_UPGRADING == c->stage); |
74 | 0 | mhd_assert (NULL != c->write_buffer); |
75 | 0 | mhd_assert ((0 != c->read_buffer_offset) || (NULL == c->read_buffer)); |
76 | 0 | mhd_assert (NULL == c->upgr.c); |
77 | |
|
78 | 0 | pupgr_data = (mhd_ACTION_UPGRADE == c->rq.app_act.head_act.act) ? |
79 | 0 | &(c->rq.app_act.head_act.data.upgrd) : |
80 | 0 | &(c->rq.app_act.upl_act.data.upgrd); |
81 | | |
82 | | // TODO: Support thread-per-connection |
83 | |
|
84 | 0 | c->upgr.c = c; |
85 | 0 | if (! mhd_mutex_init (&(c->upgr.lock))) |
86 | 0 | { |
87 | 0 | c->upgr.c = NULL; |
88 | 0 | mhd_LOG_MSG (c->daemon, |
89 | 0 | MHD_SC_MUTEX_INIT_FAILURE, |
90 | 0 | "Failed to initialise mutex for HTTP-Upgraded operations"); |
91 | 0 | mhd_conn_start_closing_no_sys_res (c); |
92 | 0 | return false; |
93 | 0 | } |
94 | 0 | mhd_DLINKEDL_INIT_LINKS (c, upgr_cleanup); |
95 | 0 | mhd_stream_release_write_buffer (c); |
96 | 0 | mhd_conn_pre_upgrade (c); |
97 | |
|
98 | 0 | mhd_conn_pre_clean_part1 (c); |
99 | |
|
100 | 0 | c->stage = mhd_HTTP_STAGE_UPGRADED; |
101 | |
|
102 | 0 | mhd_assert (! c->in_proc_ready); |
103 | 0 | mhd_assert (NULL == mhd_DLINKEDL_GET_PREV (c, by_timeout)); |
104 | 0 | mhd_assert (NULL == mhd_DLINKEDL_GET_NEXT (c, by_timeout)); |
105 | 0 | mhd_assert (c != mhd_DLINKEDL_GET_FIRST (&(c->daemon->conns), def_timeout)); |
106 | 0 | mhd_assert (c != mhd_DLINKEDL_GET_LAST (&(c->daemon->conns), def_timeout)); |
107 | 0 | mhd_assert (c != mhd_DLINKEDL_GET_FIRST (&(c->daemon->conns), cust_timeout)); |
108 | 0 | mhd_assert (c != mhd_DLINKEDL_GET_LAST (&(c->daemon->conns), cust_timeout)); |
109 | |
|
110 | 0 | pupgr_data->cb (pupgr_data->cb_cls, |
111 | 0 | &(c->rq), |
112 | 0 | &(c->upgr)); |
113 | 0 | return true; |
114 | 0 | } |
115 | | |
116 | | |
117 | | MHD_EXTERN_ |
118 | | MHD_FN_PAR_NONNULL_ (1) enum MHD_StatusCode |
119 | | MHD_upgraded_close (struct MHD_UpgradedHandle *urh) |
120 | 0 | { |
121 | 0 | struct MHD_Connection *const restrict c = urh->c; |
122 | 0 | struct MHD_Daemon *const restrict d = c->daemon; |
123 | |
|
124 | 0 | if (mhd_HTTP_STAGE_UPGRADED != c->stage) /* Probably, assert would be better here */ |
125 | 0 | return MHD_SC_TOO_LATE; |
126 | | |
127 | 0 | c->stage = mhd_HTTP_STAGE_UPGRADED_CLEANING; |
128 | 0 | mhd_mutex_lock_chk (&(d->conns.upgr.ucu_lock)); |
129 | 0 | mhd_DLINKEDL_INS_LAST (&(d->conns.upgr), c, upgr_cleanup); |
130 | 0 | mhd_mutex_unlock_chk (&(d->conns.upgr.ucu_lock)); |
131 | 0 | (void) mhd_daemon_trigger_itc (d); /* Ignore result, the connection has been placed in cleanup list already */ |
132 | |
|
133 | 0 | return MHD_SC_OK; |
134 | 0 | } |
135 | | |
136 | | |
137 | | MHD_INTERNAL |
138 | | MHD_FN_PAR_NONNULL_ (1) void |
139 | | mhd_upgraded_deinit (struct MHD_Connection *restrict c) |
140 | 0 | { |
141 | 0 | mhd_assert ((mhd_HTTP_STAGE_UPGRADED_CLEANING == c->stage) || \ |
142 | 0 | (mhd_HTTP_STAGE_UPGRADED == c->stage)); |
143 | 0 | mhd_assert (c == c->upgr.c); |
144 | |
|
145 | 0 | mhd_mutex_destroy_chk (&(c->upgr.lock)); |
146 | 0 | } |