libmicrohttpd2

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

upgrade_proc.c (5532B)


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