Skip to content

Commit 1c5f4de

Browse files
committed
Add curl_multi_init
Signed-off-by: Petr Shumilov <p.shumilov@vkteam.ru>
1 parent fe446bb commit 1c5f4de

8 files changed

Lines changed: 147 additions & 18 deletions

File tree

builtin-functions/kphp-light/stdlib/curl-functions.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,11 @@ function curl_errno ($curl_handle ::: int) ::: int;
268268
/** @kphp-extern-func-info interruptible */
269269
function curl_getinfo ($curl_handle ::: int, $option ::: int = 0) ::: mixed;
270270

271+
/** @kphp-extern-func-info interruptible */
272+
function curl_multi_init () ::: int;
273+
271274
// ===== UNSUPPORTED =====
272275

273-
/** @kphp-extern-func-info stub generation-required */
274-
function curl_multi_init () ::: int;
275276
/** @kphp-extern-func-info stub generation-required */
276277
function curl_multi_add_handle ($multi_handle ::: int, $curl_handle ::: int) ::: int|false;
277278
/** @kphp-extern-func-info stub generation-required */

runtime-light/stdlib/curl/curl-multi-functions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,20 @@
99
#include <optional>
1010

1111
#include "runtime-common/core/runtime-core.h"
12+
#include "runtime-light/stdlib/curl/defs.h"
13+
#include "runtime-light/stdlib/curl/details/diagnostics.h"
1214
#include "runtime-light/stdlib/diagnostics/logs.h"
15+
#include "runtime-light/stdlib/fork/fork-functions.h"
16+
#include "runtime-light/stdlib/web-transfer-lib/composite-transfer.h"
17+
18+
inline auto f$curl_multi_init() noexcept -> kphp::coro::task<kphp::web::curl::multi_type> {
19+
auto open_res{co_await kphp::forks::id_managed(kphp::web::composite_transfer_open(kphp::web::transfer_backend::CURL))};
20+
if (!open_res.has_value()) [[unlikely]] {
21+
kphp::web::curl::print_error("Could not initialize a new curl multi handle", std::move(open_res.error()));
22+
co_return 0;
23+
}
24+
co_return (*open_res).descriptor;
25+
}
1326

1427
inline Optional<array<int64_t>> f$curl_multi_info_read([[maybe_unused]] int64_t /*unused*/,
1528
[[maybe_unused]] Optional<std::optional<std::reference_wrapper<int64_t>>> /*unused*/ = {}) {

runtime-light/stdlib/curl/defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum class PHPCURL : uint64_t {
1616
};
1717

1818
using easy_type = simple_transfer::descriptor_type;
19+
using multi_type = composite_transfer::descriptor_type;
1920

2021
constexpr auto CURL_ERROR_SIZE = 256;
2122

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Compiler for PHP (aka KPHP)
2+
// Copyright (c) 2025 LLC «V Kontakte»
3+
// Distributed under the GPL v3 License, see LICENSE.notice.txt
4+
5+
#pragma once
6+
7+
#include <cstddef>
8+
#include <expected>
9+
#include <span>
10+
#include <utility>
11+
12+
#include "runtime-light/coroutine/task.h"
13+
#include "runtime-light/stdlib/diagnostics/logs.h"
14+
#include "runtime-light/stdlib/web-transfer-lib/defs.h"
15+
#include "runtime-light/stdlib/web-transfer-lib/details/web-error.h"
16+
#include "runtime-light/stdlib/web-transfer-lib/web-state.h"
17+
#include "runtime-light/tl/tl-core.h"
18+
#include "runtime-light/tl/tl-functions.h"
19+
#include "runtime-light/tl/tl-types.h"
20+
21+
namespace kphp::web {
22+
23+
inline auto composite_transfer_open(transfer_backend backend) noexcept -> kphp::coro::task<std::expected<composite_transfer, error>> {
24+
auto session{WebInstanceState::get().session_get_or_init()};
25+
if (!session.has_value()) [[unlikely]] {
26+
kphp::log::error("failed to start or get session with Web component");
27+
}
28+
29+
if ((*session).get() == nullptr) [[unlikely]] {
30+
kphp::log::error("session with Web components has been closed");
31+
}
32+
33+
tl::CompositeWebTransferOpen web_transfer_open{.web_backend = {static_cast<tl::CompositeWebTransferOpen::web_backend_type::underlying_type>(backend)}};
34+
tl::storer tls{web_transfer_open.footprint()};
35+
web_transfer_open.store(tls);
36+
37+
kphp::stl::vector<std::byte, kphp::memory::script_allocator> resp_buf{};
38+
const auto response_buffer_provider{[&resp_buf](size_t size) noexcept -> std::span<std::byte> {
39+
resp_buf.resize(size);
40+
return {resp_buf.data(), size};
41+
}};
42+
43+
auto resp{co_await (*session).get()->client.query(tls.view(), std::move(response_buffer_provider))};
44+
if (!resp.has_value()) [[unlikely]] {
45+
kphp::log::error("failed to send request for Composite descriptor creation");
46+
}
47+
48+
tl::Either<tl::CompositeWebTransferOpenResultOk, tl::WebError> transfer_open_resp{};
49+
tl::fetcher tlf{*resp};
50+
if (!transfer_open_resp.fetch(tlf)) [[unlikely]] {
51+
kphp::log::error("failed to parse response for Composite descriptor creation");
52+
}
53+
54+
const auto result{transfer_open_resp.value};
55+
if (std::holds_alternative<tl::WebError>(result)) {
56+
co_return std::unexpected{details::process_error(std::get<tl::WebError>(result))};
57+
}
58+
59+
const auto descriptor{std::get<0>(result).descriptor.value};
60+
61+
auto& composite2config{WebInstanceState::get().composite_transfer2config};
62+
kphp::log::assertion(composite2config.contains(descriptor) == false); // NOLINT
63+
composite2config.emplace(descriptor, composite_transfer_config{});
64+
65+
co_return std::expected<composite_transfer, error>{descriptor};
66+
}
67+
68+
} // namespace kphp::web

runtime-light/stdlib/web-transfer-lib/defs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ struct simple_transfer_config {
9999
properties_type properties{};
100100
};
101101

102+
struct composite_transfer_config {
103+
properties_type properties{};
104+
};
105+
102106
struct response {
103107
string headers;
104108
string body;

runtime-light/stdlib/web-transfer-lib/web-state.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct WebInstanceState final : private vk::not_copyable {
2626
bool session_is_finished{false};
2727
kphp::stl::unordered_map<kphp::web::simple_transfer::descriptor_type, kphp::web::simple_transfer_config, kphp::memory::script_allocator>
2828
simple_transfer2config{};
29-
kphp::stl::unordered_map<kphp::web::composite_transfer::descriptor_type, kphp::web::simple_transfer_config, kphp::memory::script_allocator>
29+
kphp::stl::unordered_map<kphp::web::composite_transfer::descriptor_type, kphp::web::composite_transfer_config, kphp::memory::script_allocator>
3030
composite_transfer2config{};
3131

3232
inline auto session_get_or_init() noexcept -> std::expected<shared_session_type, int32_t>;

runtime-light/tl/tl-functions.h

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,28 @@ struct CacheFetch final {
396396

397397
// ===== WEB TRANSFER LIB =====
398398

399+
class WebTransferGetProperties final {
400+
static constexpr uint32_t WEB_TRANSFER_GET_PROPERTIES_MAGIC = 0x72B7'16DD;
401+
402+
public:
403+
tl::u8 is_simple;
404+
tl::u64 descriptor;
405+
tl::Maybe<tl::u64> property_id;
406+
407+
void store(tl::storer& tls) const noexcept {
408+
tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_MAGIC}.store(tls);
409+
is_simple.store(tls);
410+
descriptor.store(tls);
411+
property_id.store(tls);
412+
}
413+
414+
constexpr size_t footprint() const noexcept {
415+
return tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_MAGIC}.footprint() + is_simple.footprint() + descriptor.footprint() + property_id.footprint();
416+
}
417+
};
418+
419+
// ===== Simple =====
420+
399421
class SimpleWebTransferOpen final {
400422
static constexpr uint32_t SIMPLE_WEB_TRANSFER_OPEN_MAGIC = 0x24F8'98AA;
401423

@@ -463,23 +485,22 @@ class SimpleWebTransferReset final {
463485
}
464486
};
465487

466-
class WebTransferGetProperties final {
467-
static constexpr uint32_t WEB_TRANSFER_GET_PROPERTIES_MAGIC = 0x72B7'16DD;
488+
// ===== Composite =====
489+
490+
class CompositeWebTransferOpen final {
491+
static constexpr uint32_t COMPOSITE_WEB_TRANSFER_OPEN_MAGIC = 0x428F'89FF;
468492

469493
public:
470-
tl::u8 is_simple;
471-
tl::u64 descriptor;
472-
tl::Maybe<tl::u64> property_id;
494+
using web_backend_type = tl::u8;
495+
web_backend_type web_backend;
473496

474497
void store(tl::storer& tls) const noexcept {
475-
tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_MAGIC}.store(tls);
476-
is_simple.store(tls);
477-
descriptor.store(tls);
478-
property_id.store(tls);
498+
tl::magic{.value = COMPOSITE_WEB_TRANSFER_OPEN_MAGIC}.store(tls);
499+
web_backend.store(tls);
479500
}
480501

481502
constexpr size_t footprint() const noexcept {
482-
return tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_MAGIC}.footprint() + is_simple.footprint() + descriptor.footprint() + property_id.footprint();
503+
return tl::magic{.value = COMPOSITE_WEB_TRANSFER_OPEN_MAGIC}.footprint() + web_backend.footprint();
483504
}
484505
};
485506

runtime-light/tl/tl-types.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,25 @@ struct simpleWebTransferConfig final {
12361236
}
12371237
};
12381238

1239+
class WebTransferGetPropertiesResultOk final {
1240+
static constexpr uint32_t WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC = 0x48A7'16CC;
1241+
1242+
public:
1243+
tl::vector<tl::webProperty> properties;
1244+
1245+
bool fetch(tl::fetcher& tlf) noexcept {
1246+
tl::magic magic{};
1247+
bool ok{magic.fetch(tlf) && magic.expect(WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC) && properties.fetch(tlf)};
1248+
return ok;
1249+
}
1250+
1251+
constexpr size_t footprint() const noexcept {
1252+
return tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC}.footprint();
1253+
}
1254+
};
1255+
1256+
// ===== Simple =====
1257+
12391258
class SimpleWebTransferOpenResultOk final {
12401259
static constexpr uint32_t SIMPLE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC = 0x24A8'98FF;
12411260

@@ -1298,20 +1317,22 @@ class SimpleWebTransferResetResultOk final {
12981317
}
12991318
};
13001319

1301-
class WebTransferGetPropertiesResultOk final {
1302-
static constexpr uint32_t WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC = 0x48A7'16CC;
1320+
// ===== Composite =====
1321+
1322+
class CompositeWebTransferOpenResultOk final {
1323+
static constexpr uint32_t COMPOSITE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC = 0x428A'89DD;
13031324

13041325
public:
1305-
tl::vector<tl::webProperty> properties;
1326+
tl::u64 descriptor;
13061327

13071328
bool fetch(tl::fetcher& tlf) noexcept {
13081329
tl::magic magic{};
1309-
bool ok{magic.fetch(tlf) && magic.expect(WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC) && properties.fetch(tlf)};
1330+
bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC) && descriptor.fetch(tlf)};
13101331
return ok;
13111332
}
13121333

13131334
constexpr size_t footprint() const noexcept {
1314-
return tl::magic{.value = WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC}.footprint();
1335+
return tl::magic{.value = COMPOSITE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC}.footprint() + descriptor.footprint();
13151336
}
13161337
};
13171338

0 commit comments

Comments
 (0)