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#include "core/DynamicLoader.h"
22#include "web/http/SocketContextUpgradeFactorySelector.h"
23
24#ifndef DOXYGEN_SHOULD_SKIP_THIS
25
26#include "log/Logger.h"
27#include "web/http/http_utils.h"
28
29#include <cstdlib>
30#include <filesystem>
31#include <tuple>
32
33#endif /* DOXYGEN_SHOULD_SKIP_THIS */
34
35namespace web::http {
36
37 template <typename SocketContextUpgradeFactory>
38 bool SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::add(SocketContextUpgradeFactory* socketContextUpgradeFactory,
39 void* handle) {
40 bool success = false;
41
42 if (socketContextUpgradeFactory != nullptr) {
43 SocketContextPlugin socketContextPlugin = {.socketContextUpgradeFactory = socketContextUpgradeFactory, .handle = handle};
44 std::tie(std::ignore, success) = socketContextUpgradePlugins.insert({socketContextUpgradeFactory->name(), socketContextPlugin});
45 }
46
47 return success;
48 }
49
50 template <typename SocketContextUpgradeFactory>
51 bool SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::add(SocketContextUpgradeFactory* socketContextUpgradeFactory) {
52 return add(socketContextUpgradeFactory, nullptr);
53 }
55 template <typename SocketContextUpgradeFactory>
56 void SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::allowDlOpen() {
57 onlyLinked = false;
58 }
59
60 template <typename SocketContextUpgradeFactory>
61 SocketContextUpgradeFactory*
62 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::load(const std::string& socketContextUpgradeName,
63 const std::string& socketContextUpgradeFactoryLibraryFile,
64 const std::string& socketContextUpgradeFactoryFunctionName) {
65 SocketContextUpgradeFactory* socketContextUpgradeFactory = nullptr;
66
67 void* handle = core::DynamicLoader::dlOpen(socketContextUpgradeFactoryLibraryFile);
68
69 if (handle != nullptr) {
70 SocketContextUpgradeFactory* (*getSocketContextUpgradeFactory)() = reinterpret_cast<SocketContextUpgradeFactory* (*) ()>(
71 core::DynamicLoader::dlSym(handle, socketContextUpgradeFactoryFunctionName));
72
73 if (getSocketContextUpgradeFactory != nullptr) {
74 socketContextUpgradeFactory = getSocketContextUpgradeFactory();
75
76 if (socketContextUpgradeFactory != nullptr) {
77 if (add(socketContextUpgradeFactory, handle)) {
78 LOG(DEBUG) << "HTTP: SocketContextUpgradeFactory created successful: " << socketContextUpgradeName;
79 } else {
80 LOG(DEBUG) << "HTTP: UpgradeSocketContext already existing. Not using: " << socketContextUpgradeName;
81 delete socketContextUpgradeFactory;
82 socketContextUpgradeFactory = nullptr;
83 core::DynamicLoader::dlClose(handle);
84 }
85 } else {
86 LOG(ERROR) << "HTTP: SocketContextUpgradeFactory not created: " << socketContextUpgradeName;
87 core::DynamicLoader::dlClose(handle);
88 }
89 } else {
90 LOG(ERROR) << "HTTP: Optaining function \"" << socketContextUpgradeFactoryFunctionName
91 << "\" in plugin failed: " << core::DynamicLoader::dlError();
92 core::DynamicLoader::dlClose(handle);
93 }
94 }
95
96 return socketContextUpgradeFactory;
97 }
98
99 template <typename SocketContextUpgradeFactory>
100 SocketContextUpgradeFactory*
101 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::select(const std::string& socketContextUpgradeName) {
102 SocketContextUpgradeFactory* socketContextUpgradeFactory = nullptr;
103
104 if (socketContextUpgradePlugins.contains(socketContextUpgradeName)) {
105 socketContextUpgradeFactory = socketContextUpgradePlugins[socketContextUpgradeName].socketContextUpgradeFactory;
106 } else if (linkedSocketContextUpgradePlugins.contains(socketContextUpgradeName)) {
107 socketContextUpgradeFactory = linkedSocketContextUpgradePlugins[socketContextUpgradeName]();
108 add(socketContextUpgradeFactory);
109 } else if (!onlyLinked) {
110 socketContextUpgradeFactory = load(socketContextUpgradeName);
111 }
112
113 return socketContextUpgradeFactory;
114 }
115
116 template <typename SocketContextUpgradeFactory>
117 void SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::link(const std::string& socketContextUpgradeName,
118 SocketContextUpgradeFactory* (*linkedPlugin)()) {
119 if (!linkedSocketContextUpgradePlugins.contains(socketContextUpgradeName)) {
120 linkedSocketContextUpgradePlugins[socketContextUpgradeName] = linkedPlugin;
121 }
122
123 onlyLinked = true;
124 }
125
126 template <typename SocketContextUpgradeFactory>
127 void
128 SocketContextUpgradeFactorySelector<SocketContextUpgradeFactory>::unload(SocketContextUpgradeFactory* socketContextUpgradeFactory) {
129 std::string upgradeContextNames = socketContextUpgradeFactory->name();
130
131 if (socketContextUpgradePlugins.contains(upgradeContextNames)) {
132 SocketContextPlugin socketContextPlugin = socketContextUpgradePlugins[upgradeContextNames];
133 socketContextUpgradePlugins.erase(upgradeContextNames);
134
135 delete socketContextUpgradeFactory;
136
137 if (socketContextPlugin.handle != nullptr) {
138 core::DynamicLoader::dlCloseDelayed(socketContextPlugin.handle);
139 }
140 }
141 }
142
143} // namespace web::http
#define dlOpen(libFile)