libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

upgrade_proc.c (5573B)


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