SNode.C
Loading...
Searching...
No Matches
SocketContextUpgradeFactorySelector.hpp
Go to the documentation of this file.
1
2/*
3 * SNode.C - A Slim Toolkit for Network Communication
4 * Copyright (C) Volker Christian <me@vchrist.at>
5 * 2020, 2021, 2022, 2023, 2024, 2025
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/*
22 * MIT License
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy
25 * of this software and associated documentation files (the "Software"), to deal
26 * in the Software without restriction, including without limitation the rights
27 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 * copies of the Software, and to permit persons to whom the Software is
29 * furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in
32 * all copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 * THE SOFTWARE.
41 */
42
43#include "core/DynamicLoader.h"
44#include "web/http/SocketContextUpgradeFactorySelector.h"
45
46#ifndef DOXYGEN_SHOULD_SKIP_THIS
47
48#include "log/Logger.h"
49#include "web/http/http_utils.h"
50
51#include <cstdlib>
52#include <filesystem>
53#include <tuple>
54
55#endif /* DOXYGEN_SHOULD_SKIP_THIS */
56
57namespace web::http {
58
59 template <typename SocketContextUpgradeFactory>
60 bool SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::add(SocketContextUpgradeFactory* socketContextUpgradeFactory,
61 void* handle) {
62 bool success = false;
63
64 if (socketContextUpgradeFactory != nullptr) {
65 SocketContextPlugin socketContextPlugin = {.socketContextUpgradeFactory = socketContextUpgradeFactory, .handle = handle};
66 std::tie(std::ignore, success) = socketContextUpgradePlugins.insert({socketContextUpgradeFactory->name(), socketContextPlugin});
67 }
68
69 return success;
70 }
71
72 template <typename SocketContextUpgradeFactory>
73 bool SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::add(SocketContextUpgradeFactory* socketContextUpgradeFactory) {
74 return add(socketContextUpgradeFactory, nullptr);
75 }
77 template <typename SocketContextUpgradeFactory>
78 void SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::allowDlOpen() {
79 onlyLinked = false;
80 }
81
82 template <typename SocketContextUpgradeFactory>
83 SocketContextUpgradeFactory*
84 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::load(const std::string& socketContextUpgradeName,
85 const std::string& socketContextUpgradeFactoryLibraryFile,
86 const std::string& socketContextUpgradeFactoryFunctionName) {
87 SocketContextUpgradeFactory* socketContextUpgradeFactory = nullptr;
88
89 void* handle = core::DynamicLoader::dlOpen(socketContextUpgradeFactoryLibraryFile);
90
91 if (handle != nullptr) {
92 SocketContextUpgradeFactory* (*getSocketContextUpgradeFactory)() = reinterpret_cast<SocketContextUpgradeFactory* (*) ()>(
93 core::DynamicLoader::dlSym(handle, socketContextUpgradeFactoryFunctionName));
94
95 if (getSocketContextUpgradeFactory != nullptr) {
96 socketContextUpgradeFactory = getSocketContextUpgradeFactory();
97
98 if (socketContextUpgradeFactory != nullptr) {
99 if (add(socketContextUpgradeFactory, handle)) {
100 LOG(DEBUG) << "HTTP: SocketContextUpgradeFactory created successful: " << socketContextUpgradeName;
101 } else {
102 LOG(DEBUG) << "HTTP: UpgradeSocketContext already existing. Not using: " << socketContextUpgradeName;
103 delete socketContextUpgradeFactory;
104 socketContextUpgradeFactory = nullptr;
106 }
107 } else {
108 LOG(ERROR) << "HTTP: SocketContextUpgradeFactory not created: " << socketContextUpgradeName;
110 }
111 } else {
112 LOG(ERROR) << "HTTP: Optaining function \"" << socketContextUpgradeFactoryFunctionName
113 << "\" in plugin failed: " << core::DynamicLoader::dlError();
115 }
116 }
117
118 return socketContextUpgradeFactory;
119 }
120
121 template <typename SocketContextUpgradeFactory>
122 SocketContextUpgradeFactory*
123 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::select(const std::string& socketContextUpgradeName) {
124 SocketContextUpgradeFactory* socketContextUpgradeFactory = nullptr;
125
126 if (socketContextUpgradePlugins.contains(socketContextUpgradeName)) {
127 socketContextUpgradeFactory = socketContextUpgradePlugins[socketContextUpgradeName].socketContextUpgradeFactory;
128 } else if (linkedSocketContextUpgradePlugins.contains(socketContextUpgradeName)) {
129 socketContextUpgradeFactory = linkedSocketContextUpgradePlugins[socketContextUpgradeName]();
130 add(socketContextUpgradeFactory);
131 } else if (!onlyLinked) {
132 socketContextUpgradeFactory = load(socketContextUpgradeName);
133 }
134
135 return socketContextUpgradeFactory;
136 }
137
138 template <typename SocketContextUpgradeFactory>
139 void SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::link(const std::string& socketContextUpgradeName,
140 SocketContextUpgradeFactory* (*linkedPlugin)()) {
141 if (!linkedSocketContextUpgradePlugins.contains(socketContextUpgradeName)) {
142 linkedSocketContextUpgradePlugins[socketContextUpgradeName] = linkedPlugin;
143 }
144
145 onlyLinked = true;
146 }
147
148 template <typename SocketContextUpgradeFactory>
149 void
150 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::unload(SocketContextUpgradeFactory* socketContextUpgradeFactory) {
151 std::string upgradeContextNames = socketContextUpgradeFactory->name();
152
153 if (socketContextUpgradePlugins.contains(upgradeContextNames)) {
154 SocketContextPlugin socketContextPlugin = socketContextUpgradePlugins[upgradeContextNames];
155 socketContextUpgradePlugins.erase(upgradeContextNames);
156
157 delete socketContextUpgradeFactory;
158
159 if (socketContextPlugin.handle != nullptr) {
160 core::DynamicLoader::dlCloseDelayed(socketContextPlugin.handle);
161 }
162 }
163 }
164
165} // namespace web::http
#define dlOpen(libFile)
static char * dlError()
static int dlClose(void *handle)
static void * dlSym(void *handle, const std::string &symbol)
static void dlCloseDelayed(void *handle)
void link(const std::string &socketContextUpgradeName, SocketContextUpgradeFactory *(*linkedPlugin)())
bool add(SocketContextUpgradeFactory *socketContextUpgradeFactory, void *handler)
std::map< std::string, SocketContextUpgradeFactory *(*)()> linkedSocketContextUpgradePlugins
SocketContextUpgradeFactory * select(const std::string &socketContextUpgradeName)
void unload(SocketContextUpgradeFactory *socketContextUpgradeFactory)
SocketContextUpgradeFactory * load(const std::string &socketContextUpgradeName, const std::string &socketContextUpgradeFactoryLibraryFile, const std::string &socketContextUpgradeFactoryFunctionName)
bool add(SocketContextUpgradeFactory *socketContextUpgradeFactory)
std::map< std::string, SocketContextPlugin > socketContextUpgradePlugins
void prepare(Request &request, Response &response)
const std::string & get(const std::string &key, int i=0) const
Definition Response.cpp:53
SocketContextUpgradeFactory * select(Request &req, Response &res) override
SocketContextUpgradeFactory * load(const std::string &socketContextUpgradeName) override
SocketContextUpgradeFactory * select(const std::string &protocols, Request &req)
virtual void prepare(Request &request)=0
std::string::iterator to_lower(std::string &string)
std::pair< std::string, std::string > str_split(const std::string &base, char c_middle)
std::string & str_trimm(std::string &text)