Skip to content

Commit

Permalink
refactor(runtime/{serviceworker,core,ipc,http}): introduce SW priorit…
Browse files Browse the repository at this point in the history
…ies, improve conduit, clean up
  • Loading branch information
jwerle committed Jan 9, 2025
1 parent 19963a3 commit 7c3f6d6
Show file tree
Hide file tree
Showing 19 changed files with 252 additions and 100 deletions.
15 changes: 1 addition & 14 deletions src/runtime/bridge/bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,6 @@ export * from '{{url}}'
auto origin = webview::Origin(request->scheme + "://" + request->hostname);
auto serviceWorker = app->runtime.serviceWorkerManager.get(origin.name());

debug(">> %d %d %d %d",
serviceWorker != nullptr,
request->hostname != globalBundleIdentifier,
window->options.shouldPreferServiceWorker,
serviceWorker->container.registrations.size() > 0
);

if (
serviceWorker != nullptr &&
request->hostname != globalBundleIdentifier &&
Expand All @@ -486,7 +479,6 @@ export * from '{{url}}'

const auto app = App::sharedApplication();
const auto options = serviceworker::Fetch::Options { request->client };
debug("FETCH PLZ: %s", fetch.str().c_str());
const auto fetched = serviceWorker->fetch(fetch, options, [
this,
applicationResources,
Expand Down Expand Up @@ -551,7 +543,6 @@ export * from '{{url}}'
contentLocation = resourcePath.substr(applicationResources.size(), resourcePath.size());
}

debug("RESOURCE PATH: %s", resourcePath.c_str());
auto resource = filesystem::Resource(resourcePath);

if (!resource.exists()) {
Expand Down Expand Up @@ -723,6 +714,7 @@ export * from '{{url}}'
auto fetch = serviceworker::Request();
fetch.method = request->method;
fetch.scheme = request->scheme;
fetch.url.scheme = request->scheme;
fetch.url.hostname = request->hostname;
fetch.url.pathname = request->pathname;
fetch.url.searchParams.set(request->query);
Expand Down Expand Up @@ -1067,7 +1059,6 @@ export * from '{{url}}'
});
}
} else {
debug("BEFORE REGISTER: %s %s", scheme.c_str(), scope.c_str());
this->navigator.serviceWorkerServer->container.registerServiceWorker({
.type = serviceworker::Registration::Options::Type::Module,
.scriptURL = scriptURL,
Expand All @@ -1091,7 +1082,6 @@ export * from '{{url}}'
}
}

debug("REGISTER SCHEME: %s", scheme.c_str());
this->schemeHandlers.registerSchemeHandler(scheme, [this](
auto request,
auto bridge,
Expand Down Expand Up @@ -1156,10 +1146,8 @@ export * from '{{url}}'

auto origin = webview::Origin(fetch.url.str());
origin.scheme = "socket";
debug("origin: %s", origin.name().c_str());
serviceWorkerServer = app->runtime.serviceWorkerManager.get(origin.name());
if (!serviceWorkerServer) {
debug("fall back to navigator serviceWorkerServer");
serviceWorkerServer = this->navigator.serviceWorkerServer;
}

Expand All @@ -1168,7 +1156,6 @@ export * from '{{url}}'
if (scope.size() > 0) {
fetch.url.pathname = scope + fetch.url.pathname;
}
debug("fetch: %s", fetch.str().c_str());

const auto fetched = serviceWorkerServer->fetch(fetch, options, [request, callback] (auto res) mutable {
if (!request->isActive()) {
Expand Down
6 changes: 5 additions & 1 deletion src/runtime/bytes.hh
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ namespace ssc::runtime::bytes {
Buffer& operator = (Buffer&&);
Buffer& operator = (const String&);

unsigned char operator [] (size_t) const;
unsigned char& operator [] (size_t);

size_t size () const;

template <size_t size>
Expand All @@ -146,7 +149,8 @@ namespace ssc::runtime::bytes {
bool set (const unsigned char*, size_t, size_t);
bool set (const char*, size_t, size_t);

unsigned char at (size_t) const;
unsigned char at (ssize_t);
unsigned char at (ssize_t) const;
const unsigned char* data () const;
unsigned char* data ();
const Buffer slice (size_t, size_t = -1, bool = false) const;
Expand Down
33 changes: 31 additions & 2 deletions src/runtime/bytes/buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,22 @@ namespace ssc::runtime::bytes {
return *this;
}

unsigned char Buffer::operator [] (size_t byteOffset) const {
if (byteOffset >= this->byteLength) {
throw Error("Buffer::operator[]: RangeError: 'byteOffset' exceeds 'byteLength'");
}

return this->at(byteOffset);
}

unsigned char& Buffer::operator [] (size_t byteOffset) {
if (byteOffset >= this->byteLength) {
throw Error("Buffer::operator[]: RangeError: 'byteOffset' exceeds 'byteLength'");
}

return (this->buffer.bytes.get() + this->byteOffset)[byteOffset];
}

size_t Buffer::size () const {
return this->byteLength.load(std::memory_order_relaxed);
}
Expand Down Expand Up @@ -357,12 +373,25 @@ namespace ssc::runtime::bytes {
return true;
}

unsigned char Buffer::at (size_t size) const {
unsigned char Buffer::at (ssize_t size) {
if (size >= this->byteLength) {
throw Error("Buffer::at: RangeError: 'size' exceeds 'byteLength'");
}

const auto data = this->data();
if (data == nullptr) {
return 0;
}

return data[size];
}

unsigned char Buffer::at (ssize_t size) const {
if (size >= this->byteLength) {
throw Error("Buffer::at: RangeError: 'size' exceeds 'byteLength'");
}

const auto data = this->buffer.data();
const auto data = this->data();
if (data == nullptr) {
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/core/services/ai.cc
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ namespace ssc::runtime::core::services {

LLM::LLM (LLMOptions options) {
llama_log_set([](ggml_log_level level, const char* message, void* llm) {
debug("LLMSTATUS: %s", message);
// debug("LLMSTATUS: %s", message);
// llm.log(message);
}, this);

Expand Down
102 changes: 60 additions & 42 deletions src/runtime/core/services/conduit.cc
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
#include <iostream>

#include "../../runtime.hh"
#include "../../crypto.hh"
#include "../../config.hh"
#include "../../string.hh"
#include "../../bytes.hh"
#include "../../http.hh"
#include "../../env.hh"
#include "../../ipc.hh"
#include "../../url.hh"

#include "conduit.hh"

#define SHA_DIGEST_LENGTH 20

using ssc::runtime::config::getUserConfig;
using ssc::runtime::string::toUpperCase;
using ssc::runtime::crypto::rand64;
Expand Down Expand Up @@ -261,17 +256,34 @@ namespace ssc::runtime::core::services {
Conduit::Client* client,
const char* buffer
) {
const auto request = http::Request(buffer);
auto request = http::Request(buffer);
request.url.hostname = "127.0.0.1";
request.url.scheme = "ws";
request.scheme = "ws";

if (!request.valid()) {
// TODO(@jwerle); handle malformed handshake request
client->close();
return;
}

const auto webSocketKey = request.headers.get("sec-websocket-key");

if (webSocketKey.empty()) {
// debug("Sec-WebSocket-Key is required but missing.");
const auto buffer = bytes::Buffer(http::Response(400).str());
client->write(buffer, [client]() {
client->close();
});
return;
}

const auto sharedKey = request.url.searchParams.get("key").str();
if (sharedKey != this->sharedKey) {
// debug("Conduit::Client failed auth");
const auto buffer = bytes::Buffer(http::Response(403).str());
client->write(buffer, [client]() {
client->close();
});
return;
}

Expand All @@ -283,7 +295,7 @@ namespace ssc::runtime::core::services {
}

try {
client->clientId = request.url.pathComponents.get<int>(1);
client->client.id = request.url.pathComponents.get<int>(1);
} catch (...) {
// debug("Unable to parse client id");
}
Expand All @@ -306,45 +318,16 @@ namespace ssc::runtime::core::services {
// std::cout << "added client " << this->clients.size() << std::endl;
} while (0);

if (sharedKey != this->sharedKey) {
debug("Conduit::Client failed auth");
client->close();
return;
}

const auto response = http::Response(101)
.setHeader("upgrade", "websocket")
.setHeader("connection", "upgrade")
.setHeader(
"sec-websocket-accept",
bytes::base64::encode(sha1(webSocketKey + WS_GUID))
);

const auto output = response.str();
const auto size = output.size();
const auto data = new char[size]{0};
memcpy(data, output.c_str(), size);

const auto buf = uv_buf_init(data, size);

auto req = new uv_write_t;
auto handle = reinterpret_cast<uv_handle_t*>(req);
auto stream = reinterpret_cast<uv_stream_t*>(&client->handle);

uv_handle_set_data(handle, data);
uv_write(req, stream, &buf, 1, [](uv_write_t *req, int status) {
const auto data = reinterpret_cast<char*>(
uv_handle_get_data(reinterpret_cast<uv_handle_t*>(req))
bytes::base64::encode(crypto::SHA1(webSocketKey + WS_GUID).finalize())
);

if (data != nullptr) {
delete [] data;
}

delete req;
});

client->isHandshakeDone = 1;
client->write(response.str());
client->isHandshakeDone = true;
}

void Conduit::processFrame (
Expand Down Expand Up @@ -488,8 +471,8 @@ namespace ssc::runtime::core::services {
const auto bytes = vectorToSharedPointer(buffer);
const auto message = ipc::Message(uri);

auto window = client && client->clientId > 0
? this->context.getRuntime()->windowManager.getWindowForClient({ client->clientId })
auto window = client && client->client.id > 0
? this->context.getRuntime()->windowManager.getWindowForClient({ client->client.id })
: nullptr;

// prevent external usage of internal routes
Expand Down Expand Up @@ -649,6 +632,41 @@ namespace ssc::runtime::core::services {
return true;
}

bool Conduit::Client::write (const bytes::Buffer& buffer, const WriteCallback callback) {
auto buf = uv_buf_init(reinterpret_cast<char*>(const_cast<unsigned char*>(buffer.data())), buffer.size());
auto req = new uv_write_t;
auto handle = reinterpret_cast<uv_handle_t*>(req);
auto stream = reinterpret_cast<uv_stream_t*>(&this->handle);

if (callback != nullptr) {
uv_handle_set_data(
reinterpret_cast<uv_handle_t*>(req),
new ClientWriteContext { this, callback }
);
} else {
uv_handle_set_data(
reinterpret_cast<uv_handle_t*>(req),
nullptr
);
}

uv_write(req, stream, &buf, 1, [](uv_write_t *req, int status) {
const auto data = uv_handle_get_data(reinterpret_cast<uv_handle_t*>(req));
const auto context = static_cast<ClientWriteContext*>(data);

delete req;

if (context != nullptr) {
context->client->conduit->loop.dispatch([=]() mutable {
context->callback();
delete context;
});
}
});

return true;
}

struct ClientCloseContext {
Conduit::Client* client = nullptr;
Conduit::Client::CloseCallback callback = nullptr;
Expand Down
20 changes: 14 additions & 6 deletions src/runtime/core/services/conduit.hh
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#ifndef SOCKET_RUNTIME_CORE_SERVICES_CONDUIT_H
#define SOCKET_RUNTIME_CORE_SERVICES_CONDUIT_H

#include "../../core.hh"
#include "../../ipc.hh"
#include "../../core.hh"
#include "../../bytes.hh"

namespace ssc::runtime::core::services {
class Conduit : public core::Service {
Expand Down Expand Up @@ -39,13 +40,13 @@ namespace ssc::runtime::core::services {

class Client {
public:
using CloseCallback = Function<void()>;
using SendCallback = Function<void()>;
using WriteCallback = Function<void()>;
using CloseCallback = Function<void()>;
using ID = uint64_t;

ID id = 0;
// client state
ID clientId = 0;
ipc::Client client;
Atomic<bool> isHandshakeDone = false;
Atomic<bool> isClosing = false;
Atomic<bool> isClosed = false;
Expand All @@ -64,13 +65,20 @@ namespace ssc::runtime::core::services {
Client (Conduit* conduit)
: conduit(conduit),
id(0),
clientId(0),
isHandshakeDone(0)
{}

~Client ();

bool send ( const Message::Options&, SharedPointer<unsigned char[]>, size_t, int opcode = 2, const SendCallback = nullptr);
bool send (
const Message::Options&,
SharedPointer<unsigned char[]>,
size_t,
int opcode = 2,
const SendCallback = nullptr
);

bool write (const bytes::Buffer&, const WriteCallback = nullptr);
void close (const CloseCallback callback = nullptr);
};

Expand Down
1 change: 0 additions & 1 deletion src/runtime/crypto/sha1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,4 @@ namespace ssc::runtime::crypto {
const String sha1 (const unsigned char * input, size_t size) {
return SHA1(input, size).str();
}

}
4 changes: 2 additions & 2 deletions src/runtime/http/headers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ namespace ssc::runtime::http {

headers << name << ": " << entry.value.str();
if (--remaining > 0) {
headers << "\n";
headers << "\r\n";
}
}

return headers.str() + "\r\n";
return headers.str() + "\r\n\r\n";
}

const Headers::Iterator Headers::begin () const noexcept {
Expand Down
Loading

0 comments on commit 7c3f6d6

Please sign in to comment.