Coverage Report

Created: 2025-08-26 06:30

/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
}