Skip to content

Commit

Permalink
[k2] refactor TL library (#1203)
Browse files Browse the repository at this point in the history
* remove dependency from runtime-core
* introduce tl::string
  • Loading branch information
apolyakov authored Jan 14, 2025
1 parent e10967d commit 29f2b81
Show file tree
Hide file tree
Showing 20 changed files with 535 additions and 576 deletions.
10 changes: 10 additions & 0 deletions runtime-light/allocator/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ struct script_allocator {
}
};

template<class T, class U>
constexpr bool operator==(const script_allocator<T> & /*unused*/, const script_allocator<U> & /*unused*/) {
return true;
}

template<class T, class U>
constexpr bool operator!=(const script_allocator<T> & /*unused*/, const script_allocator<U> & /*unused*/) {
return false;
}

} // namespace memory

} // namespace kphp
2 changes: 1 addition & 1 deletion runtime-light/k2-platform/k2-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ inline constexpr int32_t errno_einval = EINVAL;

inline constexpr uint64_t INVALID_PLATFORM_DESCRIPTOR = 0;

enum class StreamKind : uint8_t { Component, UDP, TCP };
enum class stream_kind : uint8_t { component, udp, tcp };

using IOStatus = IOStatus;

Expand Down
168 changes: 86 additions & 82 deletions runtime-light/server/http/init-functions.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion runtime-light/server/job-worker/init-functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ inline void init_job_server(tl::K2InvokeJobWorker &&invoke_jw) noexcept {
jw_server_ctx.kind = invoke_jw.ignore_answer ? JobWorkerServerInstanceState::Kind::NoReply : JobWorkerServerInstanceState::Kind::Regular;
jw_server_ctx.state = JobWorkerServerInstanceState::State::Working;
jw_server_ctx.job_id = invoke_jw.job_id;
jw_server_ctx.body = std::move(invoke_jw.body);
jw_server_ctx.body = {invoke_jw.body.value.data(), static_cast<string::size_type>(invoke_jw.body.value.size())};

{
using namespace PhpServerSuperGlobalIndices;
Expand Down
2 changes: 1 addition & 1 deletion runtime-light/state/init-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void process_k2_invoke_job_worker(tl::TLBuffer &tlb) noexcept {
php_error("erroneous job worker request");
}
php_assert(invoke_jw.image_id == k2::describe()->build_timestamp); // ensure that we got the request from ourselves
init_server(ServerQuery{std::move(invoke_jw)});
init_server(ServerQuery{invoke_jw});
}

} // namespace
Expand Down
8 changes: 4 additions & 4 deletions runtime-light/state/instance-state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,17 +178,17 @@ uint64_t InstanceState::take_incoming_stream() noexcept {
return stream_d;
}

std::pair<uint64_t, int32_t> InstanceState::open_stream(std::string_view component_name, k2::StreamKind stream_kind) noexcept {
std::pair<uint64_t, int32_t> InstanceState::open_stream(std::string_view component_name, k2::stream_kind stream_kind) noexcept {
uint64_t stream_d{};
int32_t error_code{};
switch (stream_kind) {
case k2::StreamKind::Component:
case k2::stream_kind::component:
error_code = k2::open(std::addressof(stream_d), component_name.size(), component_name.data());
break;
case k2::StreamKind::TCP:
case k2::stream_kind::tcp:
error_code = k2::tcp_connect(std::addressof(stream_d), component_name.data(), component_name.size());
break;
case k2::StreamKind::UDP:
case k2::stream_kind::udp:
error_code = k2::udp_connect(std::addressof(stream_d), component_name.data(), component_name.size());
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion runtime-light/state/instance-state.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct InstanceState final : vk::not_copyable {
}
uint64_t take_incoming_stream() noexcept;

std::pair<uint64_t, int32_t> open_stream(std::string_view, k2::StreamKind) noexcept;
std::pair<uint64_t, int32_t> open_stream(std::string_view, k2::stream_kind) noexcept;
std::pair<uint64_t, int32_t> set_timer(std::chrono::nanoseconds) noexcept;

void release_stream(uint64_t) noexcept;
Expand Down
2 changes: 1 addition & 1 deletion runtime-light/stdlib/component/component-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// === component query client interface ===========================================================

task_t<class_instance<C$ComponentQuery>> f$component_client_send_request(string name, string message) noexcept {
const auto [stream_d, errc]{InstanceState::get().open_stream({name.c_str(), name.size()}, k2::StreamKind::Component)};
const auto [stream_d, errc]{InstanceState::get().open_stream({name.c_str(), name.size()}, k2::stream_kind::component)};
if (errc != k2::errno_ok) {
co_return class_instance<C$ComponentQuery>{};
}
Expand Down
28 changes: 15 additions & 13 deletions runtime-light/stdlib/confdata/confdata-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ namespace {

constexpr std::string_view CONFDATA_COMPONENT_NAME = "confdata"; // TODO: it may actually have an alias specified in linking config

mixed extract_confdata_value(tl::confdataValue &&confdata_value) noexcept {
if (confdata_value.is_php_serialized && confdata_value.is_json_serialized) { // check that we don't have both flags set
mixed extract_confdata_value(const tl::confdataValue &confdata_value) noexcept {
if (confdata_value.is_php_serialized.value && confdata_value.is_json_serialized.value) { // check that we don't have both flags set
php_warning("confdata value has both php_serialized and json_serialized flags set");
return {};
}
if (confdata_value.is_php_serialized) {
return f$unserialize(confdata_value.value);
} else if (confdata_value.is_json_serialized) {
return f$json_decode(confdata_value.value);
if (confdata_value.is_php_serialized.value) {
return f$unserialize(string{confdata_value.value.value.data(), static_cast<string::size_type>(confdata_value.value.value.size())});
} else if (confdata_value.is_json_serialized.value) {
return f$json_decode(string{confdata_value.value.value.data(), static_cast<string::size_type>(confdata_value.value.value.size())});
} else {
return std::move(confdata_value.value);
return string{confdata_value.value.value.data(), static_cast<string::size_type>(confdata_value.value.value.size())};
}
}

Expand All @@ -44,7 +44,7 @@ mixed extract_confdata_value(tl::confdataValue &&confdata_value) noexcept {
// TODO: the performance of this implementation can be enhanced. rework it when the platform has specific API for that
bool f$is_confdata_loaded() noexcept {
auto &instance_st{InstanceState::get()};
if (const auto [stream_d, errc]{instance_st.open_stream(CONFDATA_COMPONENT_NAME, k2::StreamKind::Component)}; errc == k2::errno_ok) {
if (const auto [stream_d, errc]{instance_st.open_stream(CONFDATA_COMPONENT_NAME, k2::stream_kind::component)}; errc == k2::errno_ok) {
instance_st.release_stream(stream_d);
return true;
}
Expand All @@ -53,7 +53,7 @@ bool f$is_confdata_loaded() noexcept {

task_t<mixed> f$confdata_get_value(string key) noexcept {
tl::TLBuffer tlb{};
tl::ConfdataGet{.key = std::move(key)}.store(tlb);
tl::ConfdataGet{.key = {.value = {key.c_str(), key.size()}}}.store(tlb);

auto query{co_await f$component_client_send_request({CONFDATA_COMPONENT_NAME.data(), static_cast<string::size_type>(CONFDATA_COMPONENT_NAME.size())},
{tlb.data(), static_cast<string::size_type>(tlb.size())})};
Expand All @@ -70,12 +70,12 @@ task_t<mixed> f$confdata_get_value(string key) noexcept {
if (!maybe_confdata_value.opt_value.has_value()) { // no such key
co_return mixed{};
}
co_return extract_confdata_value(*std::move(maybe_confdata_value.opt_value)); // the key exists
co_return extract_confdata_value(*maybe_confdata_value.opt_value); // the key exists
}

task_t<array<mixed>> f$confdata_get_values_by_any_wildcard(string wildcard) noexcept {
tl::TLBuffer tlb{};
tl::ConfdataGetWildcard{.wildcard = std::move(wildcard)}.store(tlb);
tl::ConfdataGetWildcard{.wildcard = {.value = {wildcard.c_str(), wildcard.size()}}}.store(tlb);

auto query{co_await f$component_client_send_request({CONFDATA_COMPONENT_NAME.data(), static_cast<string::size_type>(CONFDATA_COMPONENT_NAME.size())},
{tlb.data(), static_cast<string::size_type>(tlb.size())})};
Expand All @@ -90,7 +90,9 @@ task_t<array<mixed>> f$confdata_get_values_by_any_wildcard(string wildcard) noex
}

array<mixed> result{array_size{static_cast<int64_t>(dict_confdata_value.size()), false}};
std::for_each(dict_confdata_value.begin(), dict_confdata_value.end(),
[&result](auto &&dict_field) { result.set_value(std::move(dict_field.key), extract_confdata_value(std::move(dict_field.value))); });
std::for_each(dict_confdata_value.begin(), dict_confdata_value.end(), [&result](auto &&dict_field) {
result.set_value(string{dict_field.key.value.data(), static_cast<string::size_type>(dict_field.key.value.size())},
extract_confdata_value(std::move(dict_field.value)));
});
co_return std::move(result);
}
100 changes: 71 additions & 29 deletions runtime-light/stdlib/crypto/crypto-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "runtime-light/stdlib/crypto/crypto-functions.h"

#include <cstddef>
#include <string_view>

#include "common/tl/constants/common.h"
#include "runtime-common/stdlib/server/url-functions.h"
Expand All @@ -15,7 +16,7 @@

namespace {

constexpr const char *CRYPTO_COMPONENT_NAME = "crypto";
constexpr std::string_view CRYPTO_COMPONENT_NAME = "crypto";

} // namespace

Expand All @@ -31,7 +32,8 @@ task_t<Optional<string>> f$openssl_random_pseudo_bytes(int64_t length) noexcept
tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string{buffer.data(), static_cast<string::size_type>(buffer.size())});
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string{buffer.data(), static_cast<string::size_type>(buffer.size())});
string resp = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
Expand All @@ -42,37 +44,69 @@ task_t<Optional<string>> f$openssl_random_pseudo_bytes(int64_t length) noexcept
if (!magic.has_value() || *magic != TL_MAYBE_TRUE) {
co_return false;
}
std::string_view str_view = buffer.fetch_string();
co_return string(str_view.data(), str_view.size());

tl::string str{};
str.fetch(buffer);
co_return string{str.value.data(), static_cast<string::size_type>(str.value.size())};
}

task_t<Optional<array<mixed>>> f$openssl_x509_parse(const string &data, bool shortnames) noexcept {
tl::GetPemCertInfo request{.is_short = shortnames, .bytes = data};
tl::GetPemCertInfo request{.is_short = shortnames, .bytes = {.value = {data.c_str(), data.size()}}};

tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string{buffer.data(), static_cast<string::size_type>(buffer.size())});
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string{buffer.data(), static_cast<string::size_type>(buffer.size())});
string resp_from_platform = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
buffer.store_bytes({resp_from_platform.c_str(), static_cast<size_t>(resp_from_platform.size())});

tl::GetPemCertInfoResponse response;
if (!response.fetch(buffer)) {
tl::Maybe<tl::Dictionary<tl::CertInfoItem>> cert_items;
if (!cert_items.fetch(buffer)) {
co_return false;
}
if (!cert_items.opt_value.has_value()) {
co_return false;
}

co_return response.data;
array<mixed> response;
response.reserve(cert_items.opt_value->size(), false);

auto item_to_mixed =
tl::CertInfoItem::MakeVisitor{[](int64_t val) -> mixed { return val; }, [](tl::string val) -> mixed { return string(val.value.data(), val.value.size()); },
[](const tl::dictionary<tl::string> &sub_dict) -> mixed {
array<mixed> resp;
resp.reserve(sub_dict.size(), false);
for (auto sub_item : sub_dict) {
auto key = string(sub_item.key.value.data(), sub_item.key.value.size());
auto value = string(sub_item.value.value.data(), sub_item.value.value.size());
resp[key] = value;
}

return resp;
}};

for (auto cert_kv : std::move(*cert_items.opt_value)) {
auto key = string(cert_kv.key.value.data(), cert_kv.key.value.size());
tl::CertInfoItem val = std::move(cert_kv.value);
response[string(cert_kv.key.value.data(), cert_kv.key.value.size())] = std::visit(item_to_mixed, val.data);
}

co_return response;
}

task_t<bool> f$openssl_sign(const string &data, string &signature, const string &private_key, int64_t algo) noexcept {
tl::DigestSign request{.data = data, .private_key = private_key, .algorithm = static_cast<tl::DigestAlgorithm>(algo)};
tl::DigestSign request{.data = {.value = {data.c_str(), data.size()}},
.private_key = {.value = {private_key.c_str(), private_key.size()}},
.algorithm = static_cast<tl::DigestAlgorithm>(algo)};

tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string(buffer.data(), buffer.size()));
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string(buffer.data(), buffer.size()));
string resp_from_platform = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
Expand All @@ -83,19 +117,24 @@ task_t<bool> f$openssl_sign(const string &data, string &signature, const string
co_return false;
}

std::string_view str_view = buffer.fetch_string();
signature = string(str_view.data(), str_view.size());
tl::string str{};
str.fetch(buffer);
signature = string{str.value.data(), static_cast<string::size_type>(str.value.size())};

co_return true;
}

task_t<int64_t> f$openssl_verify(const string &data, const string &signature, const string &pub_key, int64_t algo) noexcept {
tl::DigestVerify request{.data = data, .public_key = pub_key, .algorithm = static_cast<tl::DigestAlgorithm>(algo), .signature = signature};
tl::DigestVerify request{.data = {.value = {data.c_str(), data.size()}},
.public_key = {.value = {pub_key.c_str(), pub_key.size()}},
.algorithm = static_cast<tl::DigestAlgorithm>(algo),
.signature = {.value = {signature.c_str(), signature.size()}}};

tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string(buffer.data(), buffer.size()));
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string(buffer.data(), buffer.size()));
string resp_from_platform = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
Expand Down Expand Up @@ -230,25 +269,27 @@ task_t<Optional<string>> f$openssl_encrypt(const string &data, const string &met
}
tl::CbcEncrypt request{.algorithm = *algorithm,
.padding = tl::BlockPadding::PKCS7,
.passphrase = std::move(key_iv.val().first),
.iv = std::move(key_iv.val().second),
.data = data};
.passphrase = {.value = {key_iv.val().first.c_str(), key_iv.val().first.size()}},
.iv = {.value = {key_iv.val().second.c_str(), key_iv.val().second.size()}},
.data = {.value = {data.c_str(), data.size()}}};

tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string{buffer.data(), static_cast<string::size_type>(buffer.size())});
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string{buffer.data(), static_cast<string::size_type>(buffer.size())});
string resp = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
buffer.store_bytes({resp.c_str(), static_cast<size_t>(resp.size())});

tl::String response{.value = resp};
// TODO: parse error?
if (!response.fetch(buffer)) {
string response{};
if (tl::String response_{}; response_.fetch(buffer)) {
response = {response_.inner.value.data(), static_cast<string::size_type>(response_.inner.value.size())};
} else {
co_return false;
}
co_return(options & static_cast<int64_t>(cipher_opts::OPENSSL_RAW_DATA)) ? std::move(response.value) : f$base64_encode(response.value);
co_return(options & static_cast<int64_t>(cipher_opts::OPENSSL_RAW_DATA)) ? std::move(response) : f$base64_encode(response);
}

task_t<Optional<string>> f$openssl_decrypt(string data, const string &method, const string &source_key, int64_t options, const string &source_iv, string tag,
Expand Down Expand Up @@ -281,23 +322,24 @@ task_t<Optional<string>> f$openssl_decrypt(string data, const string &method, co
}
tl::CbcDecrypt request{.algorithm = *algorithm,
.padding = tl::BlockPadding::PKCS7,
.passphrase = std::move(key_iv.val().first),
.iv = std::move(key_iv.val().second),
.data = data};
.passphrase = {.value = {key_iv.val().first.c_str(), key_iv.val().first.size()}},
.iv = {.value = {key_iv.val().second.c_str(), key_iv.val().second.size()}},
.data = {.value = {data.c_str(), data.size()}}};

tl::TLBuffer buffer;
request.store(buffer);

auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME}, string{buffer.data(), static_cast<string::size_type>(buffer.size())});
auto query = f$component_client_send_request(string{CRYPTO_COMPONENT_NAME.data(), static_cast<string::size_type>(CRYPTO_COMPONENT_NAME.size())},
string{buffer.data(), static_cast<string::size_type>(buffer.size())});
string resp = co_await f$component_client_fetch_response(co_await query);

buffer.clean();
buffer.store_bytes({resp.c_str(), static_cast<size_t>(resp.size())});

tl::String response{.value = resp};
tl::String response{};
// TODO: parse error?
if (!response.fetch(buffer)) {
co_return false;
}
co_return std::move(response.value);
co_return string{response.inner.value.data(), static_cast<string::size_type>(response.inner.value.size())};
}
2 changes: 1 addition & 1 deletion runtime-light/stdlib/file/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ underlying_resource_t::underlying_resource_t(std::string_view scheme) noexcept
}
case resource_kind::UDP: {
const auto url{scheme.substr(resource_impl_::UDP_SCHEME_PREFIX.size(), scheme.size() - resource_impl_::UDP_SCHEME_PREFIX.size())};
std::tie(stream_d_, last_errc) = instance_st.open_stream(url, k2::StreamKind::UDP);
std::tie(stream_d_, last_errc) = instance_st.open_stream(url, k2::stream_kind::udp);
kind = last_errc == k2::errno_ok ? resource_kind::UDP : resource_kind::UNKNOWN;
break;
}
Expand Down
Loading

0 comments on commit 29f2b81

Please sign in to comment.