Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPWebUnixHost.h"
24 : #include "SPWebHostComponent.h"
25 : #include "SPWebRequestFilter.h"
26 : #include "SPWebWebsocketManager.h"
27 : #include "SPWebUnixWebsocket.h"
28 : #include "SPDso.h"
29 : #include "SPValid.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::web {
32 :
33 0 : UnixHostController::~UnixHostController() { }
34 :
35 25 : UnixHostController::UnixHostController(Root *root, pool_t *p, UnixHostConfig &cfg)
36 25 : : HostController(root, p) {
37 25 : _hostInfo.hostname = cfg.hastname.pdup(p);
38 25 : _hostInfo.admin = cfg.admin.pdup(p);
39 25 : _hostInfo.documentRoot = cfg.root.pdup(p);
40 :
41 25 : _componentsToLoad = move(cfg.components);
42 50 : for (auto &it : _componentsToLoad) {
43 25 : if (!it.file.empty()) { it.file = it.file.pdup(_rootPool); }
44 25 : if (!it.name.empty()) { it.name = it.name.pdup(_rootPool); }
45 25 : if (!it.version.empty()) { it.version = it.version.pdup(_rootPool); }
46 25 : if (!it.symbol.empty()) { it.symbol = it.symbol.pdup(_rootPool); }
47 : }
48 :
49 25 : if (cfg.db) {
50 175 : for (auto &it : cfg.db.asDict()) {
51 150 : _dbParams.emplace(StringView(it.first).pdup(p), StringView(it.second.getString()).pdup(p));
52 : }
53 : }
54 25 : }
55 :
56 25 : bool UnixHostController::simulateWebsocket(UnixWebsocketSim *sim, StringView url) {
57 25 : auto tmp = url;
58 25 : auto sub = tmp.readUntil<StringView::Chars<'?'>>();
59 25 : auto it = _websockets.find(sub);
60 25 : if (it == _websockets.end()) {
61 0 : return false;
62 : }
63 :
64 25 : UnixRequestController *cfg = nullptr;
65 25 : allocator_t *alloc = nullptr;
66 25 : pool_t *pool = nullptr;
67 :
68 25 : alloc = allocator::create();
69 25 : pool = pool::create(alloc, memory::PoolFlags::None);
70 :
71 50 : return perform([&] {
72 25 : auto key = base64::encode<Interface>(valid::makeRandomBytes<Interface>(16));
73 25 : auto requestSource = toString("GET ", url, " HTTP/1.1\r\n"
74 50 : "Host: ", _hostInfo.hostname, "\r\n"
75 : "sec-websocket-version: 13\r\n"
76 25 : "sec-websocket-key: ", key, "\r\n");
77 25 : StringView source(requestSource);
78 25 : RequestInfo info;
79 25 : RequestFilter::readRequestLine(source, info);
80 :
81 25 : cfg = new (pool) UnixRequestController(pool, info.clone(pool), sim);
82 25 : cfg->bind(this);
83 25 : cfg->init();
84 :
85 25 : BytesView bytes((const uint8_t *)source.data(), source.size());
86 125 : while (!bytes.empty()) {
87 100 : StringView name;
88 100 : StringView value;
89 :
90 100 : if (RequestFilter::readRequestHeader(bytes, name, value) > 0) {
91 75 : cfg->setRequestHeader(name, value);
92 : }
93 : }
94 :
95 25 : sim->attachRequest(alloc, pool, cfg);
96 :
97 25 : Request req(cfg);
98 0 : perform([&] {
99 50 : it->second->accept(req);
100 25 : }, pool, config::TAG_REQUEST, cfg);
101 25 : return true;
102 50 : }, pool);
103 : }
104 :
105 : }
|