WebFramework v3.0.12
Web framework for C++.
Loading...
Searching...
No Matches
LoadBalancerServer.cpp
1#include "LoadBalancerServer.h"
2
3#include "IOSocketStream.h"
4#include "Exceptions/SSLException.h"
5#include "HTTPSNetwork.h"
6
7#include "Utility/Sources.h"
8#include "Heuristics/Connections.h"
9
10using namespace std;
11
12namespace framework
13{
14 namespace load_balancer
15 {
16 LoadBalancerServer::ServerData::ServerData(utility::BaseConnectionData&& connectionData, std::unique_ptr<BaseLoadBalancerHeuristic>&& heuristic) noexcept :
17 connectionData(move(connectionData)),
18 heuristic(move(heuristic))
19 {
20
21 }
22
23 void LoadBalancerServer::clientConnection(const string& ip, SOCKET clientSocket, sockaddr addr, function<void()>& cleanup) //-V688
24 {
25 static mutex dataMutex;
26 const ServerData* serveData = nullptr;
27
28 {
29 unique_lock<mutex> lock(dataMutex);
30
31 serveData = &*min_element
32 (
33 allServers.begin(), allServers.end(),
34 [](const ServerData& left, const ServerData& right)
35 {
36 return (*left.heuristic)() < (*right.heuristic)();
37 }
38 );
39
40 serveData->heuristic->onStart();
41 }
42
43 const auto& [connectionData, heuristic] = *serveData;
44 SSL* ssl = nullptr;
45
46 if (useHTTPS)
47 {
48 ssl = SSL_new(context);
49
50 if (!ssl)
51 {
52 throw web::exceptions::SSLException(__LINE__, __FILE__);
53 }
54
55 if (!SSL_set_fd(ssl, static_cast<int>(clientSocket)))
56 {
57 SSL_free(ssl);
58
59 throw web::exceptions::SSLException(__LINE__, __FILE__);
60 }
61
62 if (int errorCode = SSL_accept(ssl); errorCode != 1)
63 {
64 throw web::exceptions::SSLException(__LINE__, __FILE__, ssl, errorCode);
65 }
66 }
67
68 streams::IOSocketStream clientStream
69 (
70 ssl ?
71 make_unique<web::HTTPSNetwork>(clientSocket, ssl, context) :
72 make_unique<web::HTTPNetwork>(clientSocket)
73 );
74 streams::IOSocketStream serverStream
75 (
76 serversHTTPS ?
77 make_unique<web::HTTPSNetwork>(connectionData.ip, connectionData.port, timeout) :
78 make_unique<web::HTTPNetwork>(connectionData.ip, connectionData.port, timeout)
79 );
80
81 while (isRunning)
82 {
83 string request;
84 string response;
85
86 clientStream >> request;
87
88 if (clientStream.eof())
89 {
90 break;
91 }
92
93 serverStream << request;
94
95 if (serverStream.eof())
96 {
97 HTTPResponse errorResponse;
98
99 resources->internalServerError(errorResponse, nullptr);
100
101 clientStream << errorResponse;
102
103 break;
104 }
105
106 serverStream >> response;
107
108 clientStream << response;
109 }
110
111 {
112 unique_lock<mutex> lock(dataMutex);
113
114 heuristic->onEnd();
115 }
116 }
117
118 LoadBalancerServer::LoadBalancerServer
119 (
120 string_view ip, string_view port, DWORD timeout, bool serversHTTPS,
121 string_view heuristicName, const vector<HMODULE>& loadSources,
122 const unordered_map<string, vector<int64_t>>& allServers, //-V688
123 const json::JSONParser& configuration, const filesystem::path& assets, uint64_t cachingSize, const filesystem::path& pathToTemplates
124 ) :
125 BaseTCPServer
126 (
127 port,
128 ip,
129 timeout,
130 true,
131 0,
132 false
133 ),
134 resources(make_shared<ResourceExecutor>(configuration, assets, cachingSize, pathToTemplates)),
135 serversHTTPS(serversHTTPS)
136 {
137 string createHeuristicFunctionName = format("create{}Heuristic", heuristicName);
138 createHeuristicFunction heuristicCreateFunction = nullptr;
139
140 if (heuristicName == "Connections")
141 {
142 heuristicCreateFunction = [](string_view ip, string_view port, bool useHTTPS) -> void* { return new Connections(ip, port, useHTTPS); };
143 }
144 else
145 {
146 for (HMODULE source : loadSources)
147 {
148 if (heuristicCreateFunction = reinterpret_cast<createHeuristicFunction>(utility::load(source, createHeuristicFunctionName)); heuristicCreateFunction)
149 {
150 break;
151 }
152 }
153
154 if (!heuristicCreateFunction)
155 {
156 throw runtime_error("Can't find heuristic");
157 }
158 }
159
160 this->allServers.reserve(allServers.size());
161
162 for (const auto& [ip, ports] : allServers)
163 {
164 for (int64_t port : ports)
165 {
166 string portString = to_string(port);
167
168 this->allServers.emplace_back
169 (
170 utility::BaseConnectionData(ip, portString, timeout),
171 unique_ptr<BaseLoadBalancerHeuristic>(static_cast<BaseLoadBalancerHeuristic*>(heuristicCreateFunction(ip, portString, serversHTTPS)))
172 );
173 }
174 }
175 }
176 }
177}