Skip to content

Commit eecdea9

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

8 files changed

Lines changed: 167 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 */
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Compiler for PHP (aka KPHP)
2+
// Copyright (c) 2024 LLC «V Kontakte»
3+
// Distributed under the GPL v3 License, see LICENSE.notice.txt
4+
5+
#pragma once
6+
7+
#include "runtime-light/stdlib/curl/curl-state.h"
8+
#include "runtime-light/stdlib/curl/curl.h"
9+
#include "runtime-light/stdlib/curl/defs.h"
10+
11+
#include <algorithm>
12+
#include <cstdint>
13+
#include <string_view>
14+
15+
#include "runtime-common/core/runtime-core.h"
16+
#include "runtime-light/stdlib/diagnostics/logs.h"
17+
#include "runtime-light/stdlib/fork/fork-functions.h"
18+
#include "runtime-light/stdlib/output/print-functions.h"
19+
#include "runtime-light/stdlib/web-transfer-lib/composite-transfer.h"
20+
21+
inline auto f$curl_multi_init() noexcept -> kphp::coro::task<kphp::web::curl::multi_type> {
22+
auto open_res{co_await kphp::forks::id_managed(kphp::web::composite_transfer_open(kphp::web::transfer_backend::CURL))};
23+
if (!open_res.has_value()) [[unlikely]] {
24+
kphp::web::curl::details::print_error("Could not initialize a new curl multi handle", std::move(open_res.error()));
25+
co_return 0;
26+
}
27+
co_return (*open_res).descriptor;
28+
}

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: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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 <cstdint>
9+
#include <expected>
10+
#include <iterator>
11+
#include <memory>
12+
#include <optional>
13+
#include <span>
14+
#include <string_view>
15+
#include <utility>
16+
17+
#include "runtime-light/coroutine/task.h"
18+
#include "runtime-light/stdlib/diagnostics/logs.h"
19+
#include "runtime-light/stdlib/web-transfer-lib/defs.h"
20+
#include "runtime-light/stdlib/web-transfer-lib/web-state.h"
21+
#include "runtime-light/stdlib/web-transfer-lib/web.h"
22+
#include "runtime-light/tl/tl-core.h"
23+
#include "runtime-light/tl/tl-functions.h"
24+
#include "runtime-light/tl/tl-types.h"
25+
26+
namespace kphp::web {
27+
28+
inline auto composite_transfer_open(transfer_backend backend) noexcept -> kphp::coro::task<std::expected<composite_transfer, error>> {
29+
auto session{WebInstanceState::get().session_get_or_init()};
30+
if (!session.has_value()) [[unlikely]] {
31+
kphp::log::error("failed to start or get session with Web component");
32+
}
33+
34+
if ((*session).get() == nullptr) [[unlikely]] {
35+
kphp::log::error("session with Web components has been closed");
36+
}
37+
38+
tl::CompositeWebTransferOpen web_transfer_open{.web_backend = {static_cast<tl::CompositeWebTransferOpen::web_backend_type::underlying_type>(backend)}};
39+
tl::storer tls{web_transfer_open.footprint()};
40+
web_transfer_open.store(tls);
41+
42+
kphp::stl::vector<std::byte, kphp::memory::script_allocator> resp_buf{};
43+
const auto response_buffer_provider{[&resp_buf](size_t size) noexcept -> std::span<std::byte> {
44+
resp_buf.resize(size);
45+
return {resp_buf.data(), size};
46+
}};
47+
48+
auto resp{co_await (*session).get()->client.query(tls.view(), std::move(response_buffer_provider))};
49+
if (!resp.has_value()) [[unlikely]] {
50+
kphp::log::error("failed to send request for Composite descriptor creation");
51+
}
52+
53+
tl::Either<tl::CompositeWebTransferOpenResultOk, tl::WebError> transfer_open_resp{};
54+
tl::fetcher tlf{*resp};
55+
if (!transfer_open_resp.fetch(tlf)) [[unlikely]] {
56+
kphp::log::error("failed to parse response for Composite descriptor creation");
57+
}
58+
59+
const auto result{transfer_open_resp.value};
60+
if (std::holds_alternative<tl::WebError>(result)) {
61+
co_return std::unexpected{details::process_error(std::get<1>(std::move(result)))};
62+
}
63+
64+
const auto descriptor{std::get<0>(result).descriptor.value};
65+
66+
auto& composite2config{WebInstanceState::get().composite_transfer2config};
67+
kphp::log::assertion(composite2config.contains(descriptor) == false);
68+
composite2config.emplace(descriptor, composite_transfer_config{});
69+
70+
co_return std::expected<composite_transfer, error>{descriptor};
71+
}
72+
73+
} // 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
@@ -101,6 +101,10 @@ struct simple_transfer_config {
101101
properties_type properties{};
102102
};
103103

104+
struct composite_transfer_config {
105+
properties_type properties{};
106+
};
107+
104108
struct response {
105109
string headers;
106110
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)