2022-10-20 11:49:27 +00:00
|
|
|
// Copyright (C) 2022 The Qt Company Ltd.
|
|
|
|
|
// Copyright (C) 2019 Giulio Girardi <giulio.girardi@protechgroup.it>
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
|
|
|
|
|
|
#include <QtCore/QFuture>
|
|
|
|
|
#include <QtCore/QList>
|
|
|
|
|
#include <QtCore/QThread>
|
|
|
|
|
#include <QtCore/qloggingcategory.h>
|
|
|
|
|
#include <QtGrpc/qabstractgrpcclient.h>
|
|
|
|
|
#include <QtProtobuf/QProtobufSerializer>
|
|
|
|
|
#include <qtgrpcglobal_p.h>
|
|
|
|
|
|
|
|
|
|
#include <grpcpp/channel.h>
|
|
|
|
|
#include <grpcpp/create_channel.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/byte_buffer.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/client_unary_call.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/rpc_method.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/slice.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/status.h>
|
|
|
|
|
#include <grpcpp/impl/codegen/sync_stream.h>
|
|
|
|
|
#include <grpcpp/security/credentials.h>
|
|
|
|
|
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
|
|
#include "qgrpcchannel.h"
|
|
|
|
|
#include "qgrpcchannel_p.h"
|
|
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
|
2022-12-16 14:10:50 +00:00
|
|
|
using namespace Qt::StringLiterals;
|
|
|
|
|
|
2022-10-20 11:49:27 +00:00
|
|
|
/*!
|
|
|
|
|
\class QGrpcChannel
|
2023-03-10 09:49:15 +00:00
|
|
|
\inmodule QtGrpc
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
\brief The QGrpcChannel class is a gRPC-cpp native api implementation of
|
2022-12-08 12:53:08 +00:00
|
|
|
QAbstractGrpcChannel interface.
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
QGrpcChannel accepts the same grpc::ChannelCredentials type that is required
|
|
|
|
|
by native-api grpc::CreateChannel.
|
2023-01-31 08:00:43 +00:00
|
|
|
\sa{https://grpc.github.io/grpc/cpp/classgrpc_1_1_channel_credentials.html}{gRPC ChannelCredentials}.
|
2022-12-08 12:53:08 +00:00
|
|
|
*/
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
static grpc::Status parseByteBuffer(const grpc::ByteBuffer &buffer, QByteArray &data)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
|
|
|
|
std::vector<grpc::Slice> slices;
|
|
|
|
|
auto status = buffer.Dump(&slices);
|
|
|
|
|
|
|
|
|
|
if (!status.ok())
|
|
|
|
|
return status;
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
for (const auto &slice : slices)
|
|
|
|
|
data.append((const char *)slice.begin(), slice.size());
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
return grpc::Status::OK;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
static grpc::ByteBuffer parseQByteArray(QByteArrayView bytearray)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
|
|
|
|
grpc::ByteBuffer buffer;
|
|
|
|
|
grpc::Slice slice(bytearray.data(), bytearray.size());
|
|
|
|
|
grpc::ByteBuffer tmp(&slice, 1);
|
|
|
|
|
buffer.Swap(&tmp);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-16 14:03:33 +00:00
|
|
|
static std::string toStdString(QLatin1StringView view)
|
|
|
|
|
{
|
|
|
|
|
return std::string(view.data(), view.size());
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-03 11:09:50 +00:00
|
|
|
static QByteArray buildRpcName(QLatin1StringView service, QLatin1StringView method)
|
|
|
|
|
{
|
|
|
|
|
return '/' % QByteArrayView(service) % '/' % QByteArrayView(method);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-16 14:03:33 +00:00
|
|
|
QGrpcChannelStream::QGrpcChannelStream(grpc::Channel *channel, QLatin1StringView method,
|
2023-02-08 14:46:54 +00:00
|
|
|
QByteArrayView data)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
|
|
|
|
grpc::ByteBuffer request = parseQByteArray(data);
|
|
|
|
|
|
|
|
|
|
reader = grpc::internal::ClientReaderFactory<grpc::ByteBuffer>::Create(
|
|
|
|
|
channel,
|
2022-12-16 14:03:33 +00:00
|
|
|
grpc::internal::RpcMethod(toStdString(method).c_str(),
|
2022-10-20 11:49:27 +00:00
|
|
|
grpc::internal::RpcMethod::SERVER_STREAMING),
|
|
|
|
|
&context, request);
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
thread = QThread::create([this] {
|
2022-10-20 11:49:27 +00:00
|
|
|
grpc::ByteBuffer response;
|
2022-12-09 12:03:04 +00:00
|
|
|
grpc::Status parseStatus;
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
while (reader->Read(&response)) {
|
|
|
|
|
QByteArray data;
|
2022-12-09 12:03:04 +00:00
|
|
|
parseStatus = parseByteBuffer(response, data);
|
|
|
|
|
if (!parseStatus.ok()) {
|
|
|
|
|
status = { static_cast<QGrpcStatus::StatusCode>(parseStatus.error_code()),
|
|
|
|
|
QString::fromStdString(parseStatus.error_message()) };
|
2022-10-20 11:49:27 +00:00
|
|
|
return; // exit thread
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
emit dataReady(data);
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
parseStatus = reader->Finish();
|
|
|
|
|
status = { static_cast<QGrpcStatus::StatusCode>(parseStatus.error_code()),
|
|
|
|
|
QString::fromStdString(parseStatus.error_message()) };
|
2022-10-20 11:49:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(thread, &QThread::finished, this, &QGrpcChannelStream::finished);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QGrpcChannelStream::start()
|
|
|
|
|
{
|
|
|
|
|
thread->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGrpcChannelStream::~QGrpcChannelStream()
|
|
|
|
|
{
|
|
|
|
|
cancel();
|
|
|
|
|
thread->wait();
|
|
|
|
|
thread->deleteLater();
|
|
|
|
|
delete reader;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QGrpcChannelStream::cancel()
|
|
|
|
|
{
|
|
|
|
|
// TODO: check thread safety
|
|
|
|
|
context.TryCancel();
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-16 14:03:33 +00:00
|
|
|
QGrpcChannelCall::QGrpcChannelCall(grpc::Channel *channel, QLatin1StringView method,
|
2023-02-08 14:46:54 +00:00
|
|
|
QByteArrayView data)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
|
|
|
|
grpc::ByteBuffer request = parseQByteArray(data);
|
2022-12-16 14:03:33 +00:00
|
|
|
thread = QThread::create([this, request, channel, method = toStdString(method)] {
|
2022-12-09 12:03:04 +00:00
|
|
|
grpc::ByteBuffer callResponse;
|
|
|
|
|
grpc::Status callStatus;
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
callStatus = grpc::internal::BlockingUnaryCall(
|
2022-10-20 11:49:27 +00:00
|
|
|
channel,
|
2022-12-16 14:03:33 +00:00
|
|
|
grpc::internal::RpcMethod(method.c_str(), grpc::internal::RpcMethod::NORMAL_RPC),
|
2022-12-09 12:03:04 +00:00
|
|
|
&context, request, &callResponse);
|
|
|
|
|
if (!callStatus.ok()) {
|
|
|
|
|
status = { static_cast<QGrpcStatus::StatusCode>(callStatus.error_code()),
|
|
|
|
|
QString::fromStdString(callStatus.error_message()) };
|
2022-10-20 11:49:27 +00:00
|
|
|
return; // exit thread
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
callStatus = parseByteBuffer(callResponse, response);
|
|
|
|
|
status = { static_cast<QGrpcStatus::StatusCode>(callStatus.error_code()),
|
|
|
|
|
QString::fromStdString(callStatus.error_message()) };
|
2022-10-20 11:49:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(thread, &QThread::finished, this, &QGrpcChannelCall::finished);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QGrpcChannelCall::start()
|
|
|
|
|
{
|
|
|
|
|
thread->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGrpcChannelCall::~QGrpcChannelCall()
|
|
|
|
|
{
|
|
|
|
|
cancel();
|
|
|
|
|
thread->wait();
|
|
|
|
|
thread->deleteLater();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QGrpcChannelCall::cancel()
|
|
|
|
|
{
|
|
|
|
|
// TODO: check thread safety
|
|
|
|
|
context.TryCancel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QGrpcChannelCall::waitForFinished(const QDeadlineTimer &deadline)
|
|
|
|
|
{
|
|
|
|
|
thread->wait(deadline);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-09 11:49:22 +00:00
|
|
|
QGrpcChannelPrivate::QGrpcChannelPrivate(const QGrpcChannelOptions &options,
|
|
|
|
|
QGrpcChannel::NativeGrpcChannelCredentials credentialsType)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
|
|
|
|
switch (credentialsType) {
|
|
|
|
|
case QGrpcChannel::InsecureChannelCredentials:
|
|
|
|
|
m_credentials = grpc::InsecureChannelCredentials();
|
2023-05-09 11:49:22 +00:00
|
|
|
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
|
2022-10-20 11:49:27 +00:00
|
|
|
break;
|
|
|
|
|
case QGrpcChannel::GoogleDefaultCredentials:
|
|
|
|
|
m_credentials = grpc::GoogleDefaultCredentials();
|
2023-05-09 11:49:22 +00:00
|
|
|
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
|
2022-10-20 11:49:27 +00:00
|
|
|
break;
|
2022-12-08 12:53:08 +00:00
|
|
|
case QGrpcChannel::SslDefaultCredentials:
|
2023-05-09 11:49:22 +00:00
|
|
|
if (auto maybeCredentialList = options.credentialList()) {
|
2022-10-20 11:49:27 +00:00
|
|
|
grpc::SslCredentialsOptions options;
|
2023-05-09 11:49:22 +00:00
|
|
|
options.pem_root_certs = (*maybeCredentialList)[0].toStdString();
|
|
|
|
|
options.pem_private_key = (*maybeCredentialList)[1].toStdString();
|
|
|
|
|
options.pem_cert_chain = (*maybeCredentialList)[2].toStdString();
|
2022-10-20 11:49:27 +00:00
|
|
|
m_credentials = grpc::SslCredentials(options);
|
2023-05-09 11:49:22 +00:00
|
|
|
} else {
|
|
|
|
|
m_credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
2023-05-09 11:49:22 +00:00
|
|
|
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
|
2022-12-08 12:53:08 +00:00
|
|
|
break;
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
QGrpcChannelPrivate::~QGrpcChannelPrivate() = default;
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-05-09 11:49:22 +00:00
|
|
|
std::shared_ptr<QGrpcCallReply> QGrpcChannelPrivate::call(
|
|
|
|
|
QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
|
|
|
|
|
[[maybe_unused]] const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-01-03 11:09:50 +00:00
|
|
|
const QByteArray rpcName = buildRpcName(service, method);
|
2023-04-21 10:01:26 +00:00
|
|
|
std::shared_ptr<QGrpcCallReply> reply(new QGrpcCallReply(serializer()));
|
2022-12-16 14:03:33 +00:00
|
|
|
QSharedPointer<QGrpcChannelCall> call(new QGrpcChannelCall(m_channel.get(),
|
2023-02-08 14:46:54 +00:00
|
|
|
QLatin1StringView(rpcName), args));
|
2022-12-09 13:03:47 +00:00
|
|
|
auto connection = std::make_shared<QMetaObject::Connection>();
|
|
|
|
|
auto abortConnection = std::make_shared<QMetaObject::Connection>();
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-01-24 09:15:40 +00:00
|
|
|
*connection = QObject::connect(call.get(), &QGrpcChannelCall::finished, reply.get(),
|
2022-12-09 12:03:04 +00:00
|
|
|
[call, reply, connection, abortConnection] {
|
2022-10-20 11:49:27 +00:00
|
|
|
if (call->status.code() == QGrpcStatus::Ok) {
|
|
|
|
|
reply->setData(call->response);
|
2023-03-07 12:38:35 +00:00
|
|
|
emit reply->finished();
|
2022-10-20 11:49:27 +00:00
|
|
|
} else {
|
|
|
|
|
reply->setData({});
|
2023-03-07 12:38:35 +00:00
|
|
|
emit reply->errorOccurred(call->status);
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QObject::disconnect(*connection);
|
|
|
|
|
QObject::disconnect(*abortConnection);
|
|
|
|
|
});
|
|
|
|
|
|
2023-01-24 09:15:40 +00:00
|
|
|
*abortConnection = QObject::connect(reply.get(), &QGrpcCallReply::errorOccurred, call.get(),
|
2022-10-20 11:49:27 +00:00
|
|
|
[call, connection,
|
|
|
|
|
abortConnection](const QGrpcStatus &status) {
|
|
|
|
|
if (status.code() == QGrpcStatus::Aborted) {
|
|
|
|
|
QObject::disconnect(*connection);
|
|
|
|
|
QObject::disconnect(*abortConnection);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
call->start();
|
2023-01-24 09:15:40 +00:00
|
|
|
return reply;
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 14:03:33 +00:00
|
|
|
QGrpcStatus QGrpcChannelPrivate::call(QLatin1StringView method, QLatin1StringView service,
|
2023-05-09 11:49:22 +00:00
|
|
|
QByteArrayView args, QByteArray &ret,
|
|
|
|
|
const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-01-03 11:09:50 +00:00
|
|
|
const QByteArray rpcName = buildRpcName(service, method);
|
2022-12-16 14:03:33 +00:00
|
|
|
QGrpcChannelCall call(m_channel.get(), QLatin1StringView(rpcName), args);
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
call.start();
|
2023-05-09 11:49:22 +00:00
|
|
|
options.deadline() ? call.waitForFinished(*options.deadline()) : call.waitForFinished();
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
ret = call.response;
|
|
|
|
|
return call.status;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-09 11:49:22 +00:00
|
|
|
std::shared_ptr<QGrpcStream> QGrpcChannelPrivate::startStream(
|
|
|
|
|
QLatin1StringView method, QLatin1StringView service, QByteArrayView arg,
|
|
|
|
|
[[maybe_unused]] const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-04-21 10:01:26 +00:00
|
|
|
std::shared_ptr<QGrpcStream> stream(new QGrpcStream(method, arg, serializer()));
|
2023-01-03 11:09:50 +00:00
|
|
|
const QByteArray rpcName = buildRpcName(service, stream->method());
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
QSharedPointer<QGrpcChannelStream> sub(new QGrpcChannelStream(m_channel.get(),
|
|
|
|
|
QLatin1StringView(rpcName),
|
|
|
|
|
stream->arg()));
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2022-12-09 13:03:47 +00:00
|
|
|
auto abortConnection = std::make_shared<QMetaObject::Connection>();
|
|
|
|
|
auto readConnection = std::make_shared<QMetaObject::Connection>();
|
|
|
|
|
auto connection = std::make_shared<QMetaObject::Connection>();
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-01-03 14:47:29 +00:00
|
|
|
auto disconnectAllConnections = [abortConnection, readConnection, connection]() {
|
2022-12-09 12:03:04 +00:00
|
|
|
QObject::disconnect(*connection);
|
|
|
|
|
QObject::disconnect(*readConnection);
|
|
|
|
|
QObject::disconnect(*abortConnection);
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-02 09:03:34 +00:00
|
|
|
*readConnection = QObject::connect(sub.get(), &QGrpcChannelStream::dataReady, stream.get(),
|
2022-12-09 12:03:04 +00:00
|
|
|
[stream](QByteArrayView data) {
|
2023-04-24 10:51:22 +00:00
|
|
|
stream->updateData(data.toByteArray());
|
2022-12-09 12:03:04 +00:00
|
|
|
});
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-02-02 09:03:34 +00:00
|
|
|
*connection = QObject::connect(sub.get(), &QGrpcChannelStream::finished, stream.get(),
|
2022-12-09 12:03:04 +00:00
|
|
|
[disconnectAllConnections, sub, stream] {
|
2022-10-20 11:49:27 +00:00
|
|
|
qGrpcDebug()
|
|
|
|
|
<< "Stream ended with server closing connection";
|
2022-12-09 12:03:04 +00:00
|
|
|
disconnectAllConnections();
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2022-12-08 12:53:08 +00:00
|
|
|
if (sub->status.code() != QGrpcStatus::Ok)
|
2023-03-07 12:38:35 +00:00
|
|
|
emit stream->errorOccurred(sub->status);
|
|
|
|
|
emit stream->finished();
|
2022-10-20 11:49:27 +00:00
|
|
|
});
|
|
|
|
|
|
2023-02-02 09:03:34 +00:00
|
|
|
*abortConnection = QObject::connect(stream.get(), &QGrpcStream::finished, sub.get(),
|
2022-12-09 12:03:04 +00:00
|
|
|
[disconnectAllConnections, sub] {
|
2022-10-20 11:49:27 +00:00
|
|
|
qGrpcDebug() << "Stream client was finished";
|
2022-12-09 12:03:04 +00:00
|
|
|
disconnectAllConnections();
|
2022-10-20 11:49:27 +00:00
|
|
|
sub->cancel();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
sub->start();
|
2023-02-02 09:03:34 +00:00
|
|
|
return stream;
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-21 10:01:26 +00:00
|
|
|
std::shared_ptr<QAbstractProtobufSerializer> QGrpcChannelPrivate::serializer() const
|
|
|
|
|
{
|
|
|
|
|
// TODO: make selection based on credentials or channel settings
|
|
|
|
|
return std::make_shared<QProtobufSerializer>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-20 11:49:27 +00:00
|
|
|
/*!
|
2023-05-09 11:49:22 +00:00
|
|
|
Constructs a gRPC channel, with \a options and \a credentialsType.
|
2023-02-21 14:40:21 +00:00
|
|
|
*/
|
2023-05-09 11:49:22 +00:00
|
|
|
QGrpcChannel::QGrpcChannel(const QGrpcChannelOptions &options,
|
|
|
|
|
NativeGrpcChannelCredentials credentialsType)
|
|
|
|
|
: QAbstractGrpcChannel(), dPtr(std::make_unique<QGrpcChannelPrivate>(options, credentialsType))
|
2022-12-09 12:03:04 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
/*!
|
|
|
|
|
Destroys the QGrpcChannel object.
|
|
|
|
|
*/
|
2022-10-20 11:49:27 +00:00
|
|
|
QGrpcChannel::~QGrpcChannel() = default;
|
|
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
/*!
|
|
|
|
|
Synchronously calls the RPC method and writes the result to the output parameter \a ret.
|
|
|
|
|
|
2023-02-02 09:03:34 +00:00
|
|
|
The RPC method name is constructed by concatenating the \a method
|
|
|
|
|
and \a service parameters and called with the \a args argument.
|
2023-05-09 11:49:22 +00:00
|
|
|
Uses \a options argument to set additional parameter for the call.
|
2023-02-21 14:40:21 +00:00
|
|
|
*/
|
2022-12-16 14:03:33 +00:00
|
|
|
QGrpcStatus QGrpcChannel::call(QLatin1StringView method, QLatin1StringView service,
|
2023-05-09 11:49:22 +00:00
|
|
|
QByteArrayView args, QByteArray &ret,
|
|
|
|
|
const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-05-09 11:49:22 +00:00
|
|
|
return dPtr->call(method, service, args, ret, options);
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
/*!
|
|
|
|
|
Asynchronously calls the RPC method.
|
|
|
|
|
|
2023-02-02 09:03:34 +00:00
|
|
|
The RPC method name is constructed by concatenating the \a method
|
|
|
|
|
and \a service parameters and called with the \a args argument.
|
2023-05-09 11:49:22 +00:00
|
|
|
Uses \a options argument to set additional parameter for the call.
|
2023-02-21 14:40:21 +00:00
|
|
|
The method can emit QGrpcCallReply::finished() and QGrpcCallReply::errorOccurred()
|
|
|
|
|
signals on a QGrpcCallReply returned object.
|
|
|
|
|
*/
|
2023-04-21 10:01:26 +00:00
|
|
|
std::shared_ptr<QGrpcCallReply> QGrpcChannel::call(QLatin1StringView method,
|
2023-05-09 11:49:22 +00:00
|
|
|
QLatin1StringView service, QByteArrayView args,
|
|
|
|
|
const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-05-09 11:49:22 +00:00
|
|
|
return dPtr->call(method, service, args, options);
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
/*!
|
2023-02-02 09:03:34 +00:00
|
|
|
Creates and starts a stream to the RPC method.
|
|
|
|
|
|
|
|
|
|
The RPC method name is constructed by concatenating the \a method
|
|
|
|
|
and \a service parameters and called with the \a arg argument.
|
2023-04-21 10:01:26 +00:00
|
|
|
Returns a shared pointer to the QGrpcStream.
|
2023-05-09 11:49:22 +00:00
|
|
|
Uses \a options argument to set additional parameter for the stream.
|
2023-02-21 14:40:21 +00:00
|
|
|
|
2023-04-24 10:51:22 +00:00
|
|
|
Calls QGrpcStream::updateData() when the stream receives data from the server.
|
2023-02-21 14:40:21 +00:00
|
|
|
The method may emit QGrpcStream::errorOccurred() when the stream has terminated with an error.
|
|
|
|
|
*/
|
2023-04-21 10:01:26 +00:00
|
|
|
std::shared_ptr<QGrpcStream> QGrpcChannel::startStream(QLatin1StringView method,
|
2023-02-02 09:03:34 +00:00
|
|
|
QLatin1StringView service,
|
2023-05-09 11:49:22 +00:00
|
|
|
QByteArrayView arg,
|
|
|
|
|
const QGrpcCallOptions &options)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-05-09 11:49:22 +00:00
|
|
|
return dPtr->startStream(method, service, arg, options);
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-21 14:40:21 +00:00
|
|
|
/*!
|
|
|
|
|
Returns the newly created QProtobufSerializer shared pointer.
|
|
|
|
|
*/
|
2022-12-09 13:03:47 +00:00
|
|
|
std::shared_ptr<QAbstractProtobufSerializer> QGrpcChannel::serializer() const
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2023-04-21 10:01:26 +00:00
|
|
|
return dPtr->serializer();
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|