mirror of https://github.com/qt/qtgrpc.git
End the native gRPC channel support
Remove the native gRPC channel implementation, respective feature and tests. Pick-to: 6.7 Change-Id: I71ef99746bb842d24f634ad52c77fee94edbe86f Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
This commit is contained in:
parent
ad6c1128c0
commit
cc54dccb64
|
|
@ -33,8 +33,8 @@
|
||||||
"Id": "gRPC",
|
"Id": "gRPC",
|
||||||
"Name": "gRPC",
|
"Name": "gRPC",
|
||||||
"QDocModule": "qtgrpc",
|
"QDocModule": "qtgrpc",
|
||||||
"QtUsage": "Used in the native gRPC channel implementation, examples and tests.",
|
"QtUsage": "Used in the gRPC examples and tests.",
|
||||||
"QtParts": ["libs", "tools", "examples" ],
|
"QtParts": [ "examples" ],
|
||||||
|
|
||||||
"SecurityCritical": false,
|
"SecurityCritical": false,
|
||||||
"Homepage": "https://grpc.io",
|
"Homepage": "https://grpc.io",
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,6 @@ qt_internal_add_module(Grpc
|
||||||
Qt::Network
|
Qt::Network
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Grpc CONDITION QT_FEATURE_native_grpc
|
|
||||||
SOURCES
|
|
||||||
qgrpcchannel.h qgrpcchannel_p.h qgrpcchannel.cpp
|
|
||||||
PUBLIC_LIBRARIES
|
|
||||||
WrapgRPC::WrapLibgRPC
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_internal_add_docs(Grpc
|
qt_internal_add_docs(Grpc
|
||||||
doc/qtgrpc.qdocconf
|
doc/qtgrpc.qdocconf
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,6 @@ qt_feature("qtgrpcgen" PRIVATE
|
||||||
TARGET WrapProtoc::WrapProtoc AND TEST_libprotobuf AND TEST_libprotoc
|
TARGET WrapProtoc::WrapProtoc AND TEST_libprotobuf AND TEST_libprotoc
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_feature("native_grpc" PUBLIC
|
|
||||||
SECTION "Utilities"
|
|
||||||
LABEL "Native gRPC support"
|
|
||||||
DISABLE NOT QT_FEATURE_grpc
|
|
||||||
PURPOSE "Provides native implementation for gRPC channels and client and service code generation."
|
|
||||||
CONDITION TARGET WrapgRPC::WrapLibgRPC
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_feature("grpcquick" PUBLIC
|
qt_feature("grpcquick" PUBLIC
|
||||||
SECTION "Utilities"
|
SECTION "Utilities"
|
||||||
LABEL "QML gRPC support"
|
LABEL "QML gRPC support"
|
||||||
|
|
@ -40,7 +32,6 @@ qt_feature("grpcquick" PUBLIC
|
||||||
qt_configure_add_summary_section(NAME "Qt GRPC")
|
qt_configure_add_summary_section(NAME "Qt GRPC")
|
||||||
qt_configure_add_summary_entry(ARGS "grpc")
|
qt_configure_add_summary_entry(ARGS "grpc")
|
||||||
qt_configure_add_summary_entry(ARGS "grpcquick")
|
qt_configure_add_summary_entry(ARGS "grpcquick")
|
||||||
qt_configure_add_summary_entry(ARGS "native_grpc")
|
|
||||||
qt_configure_end_summary_section()
|
qt_configure_end_summary_section()
|
||||||
qt_configure_add_summary_section(NAME "Qt GRPC tools")
|
qt_configure_add_summary_section(NAME "Qt GRPC tools")
|
||||||
qt_configure_add_summary_entry(ARGS "qtgrpcgen")
|
qt_configure_add_summary_entry(ARGS "qtgrpcgen")
|
||||||
|
|
|
||||||
|
|
@ -137,5 +137,5 @@
|
||||||
Furthermore, Qt GRPC in Qt \QtVersion may contain third party
|
Furthermore, Qt GRPC in Qt \QtVersion may contain third party
|
||||||
modules under the following permissive licenses:
|
modules under the following permissive licenses:
|
||||||
|
|
||||||
\generatelist{groupsbymodule attributions-qtgrpc-tools}
|
\generatelist{groupsbymodule attributions-qtgrpc-examples}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,386 +0,0 @@
|
||||||
// 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 "qgrpcchannel.h"
|
|
||||||
#include "qgrpcchannel_p.h"
|
|
||||||
#include "qgrpcchanneloperation.h"
|
|
||||||
|
|
||||||
#include "qabstractgrpcclient.h"
|
|
||||||
|
|
||||||
#include <QtCore/QFuture>
|
|
||||||
#include <QtCore/QList>
|
|
||||||
#include <QtCore/QThread>
|
|
||||||
#include <QtCore/QTimer>
|
|
||||||
#include <QtCore/qloggingcategory.h>
|
|
||||||
#include <QtProtobuf/QProtobufSerializer>
|
|
||||||
#include <qtgrpcglobal_p.h>
|
|
||||||
|
|
||||||
#include <grpcpp/channel.h>
|
|
||||||
#include <grpcpp/create_channel.h>
|
|
||||||
#include <grpcpp/completion_queue.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>
|
|
||||||
|
|
||||||
#if QT_CONFIG(ssl)
|
|
||||||
# include <QtNetwork/QSslKey>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QGrpcChannel
|
|
||||||
\inmodule QtGrpc
|
|
||||||
|
|
||||||
\brief The QGrpcHttp2Channel class is an HTTP/2 implementation of
|
|
||||||
QAbstractGrpcChannel, based on the reference gRPC C++ API.
|
|
||||||
|
|
||||||
QGrpcChannel accepts the same grpc::ChannelCredentials type that is required
|
|
||||||
by native-api grpc::CreateChannel.
|
|
||||||
\sa{https://grpc.github.io/grpc/cpp/classgrpc_1_1_channel_credentials.html}{gRPC ChannelCredentials}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static grpc::Status parseByteBuffer(const grpc::ByteBuffer &buffer, QByteArray &data)
|
|
||||||
{
|
|
||||||
std::vector<grpc::Slice> slices;
|
|
||||||
auto status = buffer.Dump(&slices);
|
|
||||||
|
|
||||||
if (!status.ok())
|
|
||||||
return status;
|
|
||||||
|
|
||||||
for (const auto &slice : slices)
|
|
||||||
data.append((const char *)slice.begin(), slice.size());
|
|
||||||
|
|
||||||
return grpc::Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grpc::ByteBuffer parseQByteArray(QByteArrayView bytearray)
|
|
||||||
{
|
|
||||||
grpc::ByteBuffer buffer;
|
|
||||||
grpc::Slice slice(bytearray.data(), bytearray.size());
|
|
||||||
grpc::ByteBuffer tmp(&slice, 1);
|
|
||||||
buffer.Swap(&tmp);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string toStdString(QLatin1StringView view)
|
|
||||||
{
|
|
||||||
return std::string(view.data(), view.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
static QByteArray buildRpcName(QLatin1StringView service, QLatin1StringView method)
|
|
||||||
{
|
|
||||||
return '/' % QByteArrayView(service) % '/' % QByteArrayView(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
QGrpcChannelStream::QGrpcChannelStream(grpc::Channel *channel, QLatin1StringView method,
|
|
||||||
QByteArrayView data)
|
|
||||||
{
|
|
||||||
grpc::ByteBuffer request = parseQByteArray(data);
|
|
||||||
|
|
||||||
reader = grpc::internal::ClientReaderFactory<grpc::ByteBuffer>::Create(
|
|
||||||
channel,
|
|
||||||
grpc::internal::RpcMethod(toStdString(method).c_str(),
|
|
||||||
grpc::internal::RpcMethod::SERVER_STREAMING),
|
|
||||||
&context, request);
|
|
||||||
|
|
||||||
thread = QThread::create([this] {
|
|
||||||
grpc::ByteBuffer response;
|
|
||||||
grpc::Status parseStatus;
|
|
||||||
|
|
||||||
while (reader->Read(&response)) {
|
|
||||||
QByteArray data;
|
|
||||||
parseStatus = parseByteBuffer(response, data);
|
|
||||||
if (!parseStatus.ok()) {
|
|
||||||
status = { static_cast<QGrpcStatus::StatusCode>(parseStatus.error_code()),
|
|
||||||
QString::fromStdString(parseStatus.error_message()) };
|
|
||||||
return; // exit thread
|
|
||||||
}
|
|
||||||
|
|
||||||
emit dataReady(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseStatus = reader->Finish();
|
|
||||||
status = { static_cast<QGrpcStatus::StatusCode>(parseStatus.error_code()),
|
|
||||||
QString::fromStdString(parseStatus.error_message()) };
|
|
||||||
});
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
QGrpcChannelCall::QGrpcChannelCall(grpc::Channel *channel, QLatin1StringView method,
|
|
||||||
QByteArrayView data)
|
|
||||||
{
|
|
||||||
grpc::ByteBuffer request = parseQByteArray(data);
|
|
||||||
thread = QThread::create([this, request, channel, method = toStdString(method)] {
|
|
||||||
grpc::ByteBuffer callResponse;
|
|
||||||
grpc::Status callStatus;
|
|
||||||
|
|
||||||
callStatus = grpc::internal::BlockingUnaryCall(
|
|
||||||
channel,
|
|
||||||
grpc::internal::RpcMethod(method.c_str(), grpc::internal::RpcMethod::NORMAL_RPC),
|
|
||||||
&context, request, &callResponse);
|
|
||||||
if (!callStatus.ok()) {
|
|
||||||
status = { static_cast<QGrpcStatus::StatusCode>(callStatus.error_code()),
|
|
||||||
QString::fromStdString(callStatus.error_message()) };
|
|
||||||
return; // exit thread
|
|
||||||
}
|
|
||||||
|
|
||||||
callStatus = parseByteBuffer(callResponse, response);
|
|
||||||
status = { static_cast<QGrpcStatus::StatusCode>(callStatus.error_code()),
|
|
||||||
QString::fromStdString(callStatus.error_message()) };
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
QGrpcChannelPrivate::QGrpcChannelPrivate(const QGrpcChannelOptions &channelOptions,
|
|
||||||
QGrpcChannel::NativeGrpcChannelCredentials credentialsType)
|
|
||||||
{
|
|
||||||
switch (credentialsType) {
|
|
||||||
case QGrpcChannel::InsecureChannelCredentials:
|
|
||||||
m_credentials = grpc::InsecureChannelCredentials();
|
|
||||||
m_channel = grpc::CreateChannel(channelOptions.host().toString().toStdString(),
|
|
||||||
m_credentials);
|
|
||||||
break;
|
|
||||||
case QGrpcChannel::GoogleDefaultCredentials:
|
|
||||||
m_credentials = grpc::GoogleDefaultCredentials();
|
|
||||||
m_channel = grpc::CreateChannel(channelOptions.host().toString().toStdString(),
|
|
||||||
m_credentials);
|
|
||||||
break;
|
|
||||||
case QGrpcChannel::SslDefaultCredentials:
|
|
||||||
#if QT_CONFIG(ssl)
|
|
||||||
if (auto maybeSslConfig = channelOptions.sslConfiguration()) {
|
|
||||||
grpc::SslCredentialsOptions options;
|
|
||||||
auto accumulateSslCert = [](const std::string &lhs, const QSslCertificate &rhs) {
|
|
||||||
return lhs + rhs.toPem().toStdString();
|
|
||||||
};
|
|
||||||
options.pem_root_certs = std::accumulate(maybeSslConfig->peerCertificateChain().begin(),
|
|
||||||
maybeSslConfig->peerCertificateChain().end(), options.pem_root_certs,
|
|
||||||
accumulateSslCert);
|
|
||||||
options.pem_cert_chain = std::accumulate(maybeSslConfig->localCertificateChain().begin(),
|
|
||||||
maybeSslConfig->localCertificateChain().end(), options.pem_cert_chain,
|
|
||||||
accumulateSslCert);
|
|
||||||
options.pem_private_key = maybeSslConfig->privateKey().toPem();
|
|
||||||
m_credentials = grpc::SslCredentials(options);
|
|
||||||
} else {
|
|
||||||
m_credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
m_credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
|
|
||||||
#endif
|
|
||||||
m_channel = grpc::CreateChannel(channelOptions.host().toString().toStdString(),
|
|
||||||
m_credentials);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QGrpcChannelPrivate::~QGrpcChannelPrivate() = default;
|
|
||||||
|
|
||||||
void QGrpcChannelPrivate::call(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
const QByteArray rpcName =
|
|
||||||
buildRpcName(channelOperation->service(), channelOperation->method());
|
|
||||||
QSharedPointer<QGrpcChannelCall> call(new QGrpcChannelCall(m_channel.get(),
|
|
||||||
QLatin1StringView(rpcName),
|
|
||||||
channelOperation->argument()));
|
|
||||||
auto connection = std::make_shared<QMetaObject::Connection>();
|
|
||||||
auto abortConnection = std::make_shared<QMetaObject::Connection>();
|
|
||||||
|
|
||||||
*connection = QObject::connect(call.get(), &QGrpcChannelCall::finished, channelOperation.get(),
|
|
||||||
[call, channelOperation, connection, abortConnection] {
|
|
||||||
QObject::disconnect(*connection);
|
|
||||||
QObject::disconnect(*abortConnection);
|
|
||||||
if (call->status == QGrpcStatus::Ok) {
|
|
||||||
channelOperation->dataReady(call->response);
|
|
||||||
} else {
|
|
||||||
emit channelOperation->errorOccurred(call->status);
|
|
||||||
}
|
|
||||||
emit channelOperation->finished();
|
|
||||||
});
|
|
||||||
|
|
||||||
*abortConnection = QObject::connect(channelOperation.get(), &QGrpcChannelOperation::cancelled,
|
|
||||||
call.get(), [connection, abortConnection]() {
|
|
||||||
QObject::disconnect(*connection);
|
|
||||||
QObject::disconnect(*abortConnection);
|
|
||||||
});
|
|
||||||
|
|
||||||
call->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QGrpcChannelPrivate::startServerStream(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
const QByteArray rpcName =
|
|
||||||
buildRpcName(channelOperation->service(), channelOperation->method());
|
|
||||||
|
|
||||||
QSharedPointer<QGrpcChannelStream> sub(new QGrpcChannelStream(m_channel.get(),
|
|
||||||
QLatin1StringView(rpcName),
|
|
||||||
channelOperation->argument()));
|
|
||||||
|
|
||||||
auto abortConnection = std::make_shared<QMetaObject::Connection>();
|
|
||||||
auto readConnection = std::make_shared<QMetaObject::Connection>();
|
|
||||||
auto connection = std::make_shared<QMetaObject::Connection>();
|
|
||||||
|
|
||||||
auto disconnectAllConnections = [abortConnection, readConnection, connection]() {
|
|
||||||
QObject::disconnect(*connection);
|
|
||||||
QObject::disconnect(*readConnection);
|
|
||||||
QObject::disconnect(*abortConnection);
|
|
||||||
};
|
|
||||||
|
|
||||||
*readConnection =
|
|
||||||
QObject::connect(sub.get(), &QGrpcChannelStream::dataReady, channelOperation.get(),
|
|
||||||
[channelOperation](QByteArrayView data) {
|
|
||||||
channelOperation->dataReady(data.toByteArray());
|
|
||||||
});
|
|
||||||
|
|
||||||
*connection = QObject::connect(sub.get(), &QGrpcChannelStream::finished, channelOperation.get(),
|
|
||||||
[disconnectAllConnections, sub, channelOperation] {
|
|
||||||
qGrpcDebug()
|
|
||||||
<< "Stream ended with server closing connection";
|
|
||||||
disconnectAllConnections();
|
|
||||||
|
|
||||||
if (sub->status != QGrpcStatus::Ok)
|
|
||||||
emit channelOperation->errorOccurred(sub->status);
|
|
||||||
emit channelOperation->finished();
|
|
||||||
});
|
|
||||||
|
|
||||||
*abortConnection =
|
|
||||||
QObject::connect(channelOperation.get(), &QGrpcChannelOperation::cancelled, sub.get(),
|
|
||||||
[disconnectAllConnections, sub, channelOperation] {
|
|
||||||
qGrpcDebug() << "Server stream was cancelled by client";
|
|
||||||
disconnectAllConnections();
|
|
||||||
sub->cancel();
|
|
||||||
});
|
|
||||||
|
|
||||||
sub->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> QGrpcChannelPrivate::serializer() const
|
|
||||||
{
|
|
||||||
// TODO: make selection based on credentials or channel settings
|
|
||||||
return std::make_shared<QProtobufSerializer>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Constructs a gRPC channel, with \a options and \a credentialsType.
|
|
||||||
*/
|
|
||||||
QGrpcChannel::QGrpcChannel(const QGrpcChannelOptions &options,
|
|
||||||
NativeGrpcChannelCredentials credentialsType)
|
|
||||||
: QAbstractGrpcChannel(options),
|
|
||||||
dPtr(std::make_unique<QGrpcChannelPrivate>(options, credentialsType))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Destroys the QGrpcChannel object.
|
|
||||||
*/
|
|
||||||
QGrpcChannel::~QGrpcChannel() = default;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
Implementation of unary gRPC call based on the
|
|
||||||
reference gRPC C++ API.
|
|
||||||
*/
|
|
||||||
void QGrpcChannel::call(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
dPtr->call(std::move(channelOperation));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
Implementation of server-side gRPC stream based on the
|
|
||||||
reference gRPC C++ API.
|
|
||||||
*/
|
|
||||||
void QGrpcChannel::startServerStream(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
dPtr->startServerStream(std::move(channelOperation));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
Implementation of client-side gRPC stream based on the
|
|
||||||
reference gRPC C++ API.
|
|
||||||
*/
|
|
||||||
void QGrpcChannel::startClientStream(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, channelOperation.get(), [channelOperation] {
|
|
||||||
emit channelOperation->errorOccurred(
|
|
||||||
{ QGrpcStatus::Unknown,
|
|
||||||
"Client-side streaming support is not implemented in QGrpcChannel"_L1 });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
Implementation of bidirectional gRPC stream based on the
|
|
||||||
reference gRPC C++ API.
|
|
||||||
*/
|
|
||||||
void QGrpcChannel::startBidirStream(std::shared_ptr<QGrpcChannelOperation> channelOperation)
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, channelOperation.get(), [channelOperation] {
|
|
||||||
emit channelOperation->errorOccurred(
|
|
||||||
{ QGrpcStatus::Unknown,
|
|
||||||
"Bidirectional streaming support is not implemented in QGrpcChannel"_L1 });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the newly created QProtobufSerializer shared pointer.
|
|
||||||
*/
|
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> QGrpcChannel::serializer() const
|
|
||||||
{
|
|
||||||
return dPtr->serializer();
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
// 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
|
|
||||||
|
|
||||||
#ifndef QGRPCCHANNEL_H
|
|
||||||
#define QGRPCCHANNEL_H
|
|
||||||
|
|
||||||
#include <QtGrpc/qabstractgrpcclient.h>
|
|
||||||
#include <QtGrpc/qgrpcchanneloptions.h>
|
|
||||||
#include <QtGrpc/qtgrpcglobal.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
struct QGrpcChannelPrivate;
|
|
||||||
|
|
||||||
class Q_GRPC_EXPORT QGrpcChannel final : public QAbstractGrpcChannel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum NativeGrpcChannelCredentials : uint8_t {
|
|
||||||
InsecureChannelCredentials = 0,
|
|
||||||
GoogleDefaultCredentials,
|
|
||||||
SslDefaultCredentials,
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QGrpcChannel(const QGrpcChannelOptions &options,
|
|
||||||
NativeGrpcChannelCredentials credentialsType);
|
|
||||||
|
|
||||||
~QGrpcChannel() override;
|
|
||||||
|
|
||||||
void call(std::shared_ptr<QGrpcChannelOperation> channelOperation) override;
|
|
||||||
void startServerStream(std::shared_ptr<QGrpcChannelOperation> channelOperation) override;
|
|
||||||
void startClientStream(std::shared_ptr<QGrpcChannelOperation> channelOperation) override;
|
|
||||||
void startBidirStream(std::shared_ptr<QGrpcChannelOperation> channelOperation) override;
|
|
||||||
|
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> serializer() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DISABLE_COPY_MOVE(QGrpcChannel)
|
|
||||||
|
|
||||||
std::unique_ptr<QGrpcChannelPrivate> dPtr;
|
|
||||||
};
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QGRPCCHANNEL_H
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
// 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
|
|
||||||
|
|
||||||
#ifndef QGRPCCHANNEL_P_H
|
|
||||||
#define QGRPCCHANNEL_P_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <QtGrpc/qabstractgrpcclient.h>
|
|
||||||
#include <QtGrpc/qgrpccallreply.h>
|
|
||||||
#include <QtGrpc/qgrpcchannel.h>
|
|
||||||
#include <QtGrpc/qgrpcstream.h>
|
|
||||||
#include <QtGrpc/private/qtgrpcglobal_p.h>
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
#include <QtCore/QThread>
|
|
||||||
#include <QtCore/qbytearray.h>
|
|
||||||
|
|
||||||
QT_REQUIRE_CONFIG(native_grpc);
|
|
||||||
#include <grpcpp/channel.h>
|
|
||||||
#include <grpcpp/impl/codegen/byte_buffer.h>
|
|
||||||
#include <grpcpp/impl/codegen/client_context.h>
|
|
||||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
|
||||||
#include <grpcpp/security/credentials.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class QGrpcChannelStream : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit QGrpcChannelStream(grpc::Channel *channel, QLatin1StringView method,
|
|
||||||
QByteArrayView data);
|
|
||||||
~QGrpcChannelStream() override;
|
|
||||||
|
|
||||||
void cancel();
|
|
||||||
void start();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void dataReady(const QByteArray &data);
|
|
||||||
void finished();
|
|
||||||
|
|
||||||
public:
|
|
||||||
QGrpcStatus status;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QThread *thread;
|
|
||||||
grpc::ClientContext context;
|
|
||||||
grpc::ClientReader<grpc::ByteBuffer> *reader = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QGrpcChannelCall : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit QGrpcChannelCall(grpc::Channel *channel, QLatin1StringView method,
|
|
||||||
QByteArrayView data);
|
|
||||||
~QGrpcChannelCall() override;
|
|
||||||
|
|
||||||
void cancel();
|
|
||||||
void start();
|
|
||||||
void waitForFinished(const QDeadlineTimer &deadline = QDeadlineTimer(QDeadlineTimer::Forever));
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void finished();
|
|
||||||
|
|
||||||
public:
|
|
||||||
QGrpcStatus status;
|
|
||||||
QByteArray response;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QThread *thread;
|
|
||||||
grpc::ClientContext context;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QGrpcChannelPrivate
|
|
||||||
{
|
|
||||||
std::shared_ptr<grpc::Channel> m_channel;
|
|
||||||
std::shared_ptr<grpc::ChannelCredentials> m_credentials;
|
|
||||||
|
|
||||||
explicit QGrpcChannelPrivate(const QGrpcChannelOptions &channelOptions,
|
|
||||||
QGrpcChannel::NativeGrpcChannelCredentials credentialsType);
|
|
||||||
~QGrpcChannelPrivate();
|
|
||||||
|
|
||||||
void call(std::shared_ptr<QGrpcChannelOperation> channelOperation);
|
|
||||||
void startServerStream(std::shared_ptr<QGrpcChannelOperation> channelOperation);
|
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> serializer() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QGRPCCHANNEL_P_H
|
|
||||||
|
|
@ -18,7 +18,7 @@ class QtGrpcClientBidirStreamTest : public GrpcClientTestBase
|
||||||
public:
|
public:
|
||||||
QtGrpcClientBidirStreamTest()
|
QtGrpcClientBidirStreamTest()
|
||||||
: GrpcClientTestBase(
|
: GrpcClientTestBase(
|
||||||
{ GrpcClientTestBase::Channel::Qt, GrpcClientTestBase::Channel::Native })
|
Channels{ GrpcClientTestBase::Channel::Qt })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,9 +28,6 @@ private slots:
|
||||||
|
|
||||||
void QtGrpcClientBidirStreamTest::Valid()
|
void QtGrpcClientBidirStreamTest::Valid()
|
||||||
{
|
{
|
||||||
if (channelType().testFlag(GrpcClientTestBase::Channel::Native))
|
|
||||||
QSKIP("Unimplemented in the reference gRPC channel.");
|
|
||||||
|
|
||||||
const int ExpectedMessageCount = 4;
|
const int ExpectedMessageCount = 4;
|
||||||
|
|
||||||
SimpleStringMessage request;
|
SimpleStringMessage request;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class QtGrpcClientClientStreamTest : public GrpcClientTestBase
|
||||||
public:
|
public:
|
||||||
QtGrpcClientClientStreamTest()
|
QtGrpcClientClientStreamTest()
|
||||||
: GrpcClientTestBase(
|
: GrpcClientTestBase(
|
||||||
{ GrpcClientTestBase::Channel::Qt, GrpcClientTestBase::Channel::Native })
|
Channels{ GrpcClientTestBase::Channel::Qt })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,9 +28,6 @@ private slots:
|
||||||
|
|
||||||
void QtGrpcClientClientStreamTest::Valid()
|
void QtGrpcClientClientStreamTest::Valid()
|
||||||
{
|
{
|
||||||
if (channelType().testFlag(GrpcClientTestBase::Channel::Native))
|
|
||||||
QSKIP("Unimplemented in the reference gRPC channel.");
|
|
||||||
|
|
||||||
const int ExpectedMessageCount = 4;
|
const int ExpectedMessageCount = 4;
|
||||||
|
|
||||||
SimpleStringMessage request;
|
SimpleStringMessage request;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class QtGrpcClientServerStreamTest : public GrpcClientTestBase
|
||||||
public:
|
public:
|
||||||
QtGrpcClientServerStreamTest()
|
QtGrpcClientServerStreamTest()
|
||||||
: GrpcClientTestBase(
|
: GrpcClientTestBase(
|
||||||
{ GrpcClientTestBase::Channel::Qt, GrpcClientTestBase::Channel::Native })
|
Channels{ GrpcClientTestBase::Channel::Qt })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,6 @@ void GrpcClientTestBase::initTestCase_data()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
if (m_channels.testFlag(Channel::Native)) {
|
|
||||||
# ifndef Q_OS_WINDOWS
|
|
||||||
QTest::newRow("GrpcSocket")
|
|
||||||
<< QFlags{ Channel::Native }
|
|
||||||
<< std::shared_ptr<QAbstractGrpcChannel>(
|
|
||||||
new QGrpcChannel(QGrpcChannelOptions{ QUrl("unix:///tmp/qtgrpc_test.sock") },
|
|
||||||
QGrpcChannel::InsecureChannelCredentials));
|
|
||||||
# endif
|
|
||||||
QTest::newRow("GrpcHttp") << QFlags{ Channel::Native }
|
|
||||||
<< std::shared_ptr<QAbstractGrpcChannel>(new QGrpcChannel(
|
|
||||||
QGrpcChannelOptions{ QUrl("localhost:50051") },
|
|
||||||
QGrpcChannel::InsecureChannelCredentials));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if QT_CONFIG(ssl)
|
#if QT_CONFIG(ssl)
|
||||||
if (m_channels.testFlag(Channel::Ssl)) {
|
if (m_channels.testFlag(Channel::Ssl)) {
|
||||||
QFile caCerificateFile(":/assets/cert.pem");
|
QFile caCerificateFile(":/assets/cert.pem");
|
||||||
|
|
@ -67,12 +51,6 @@ void GrpcClientTestBase::initTestCase_data()
|
||||||
QTest::newRow("Http2ClientSSLNoCredentials")
|
QTest::newRow("Http2ClientSSLNoCredentials")
|
||||||
<< QFlags{ Channel::Qt, Channel::SslNoCredentials }
|
<< QFlags{ Channel::Qt, Channel::SslNoCredentials }
|
||||||
<< std::shared_ptr<QAbstractGrpcChannel>(new QGrpcHttp2Channel(channelOptions));
|
<< std::shared_ptr<QAbstractGrpcChannel>(new QGrpcHttp2Channel(channelOptions));
|
||||||
# if QT_CONFIG(native_grpc)
|
|
||||||
QTest::newRow("GrpcHttpSSLNoCredentials")
|
|
||||||
<< QFlags{ Channel::Native, Channel::SslNoCredentials }
|
|
||||||
<< std::shared_ptr<QAbstractGrpcChannel>(new QGrpcChannel(channelOptions,
|
|
||||||
QGrpcChannel::SslDefaultCredentials));
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,6 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <QtGrpc/qtgrpcglobal.h>
|
#include <QtGrpc/qtgrpcglobal.h>
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
# include <QtGrpc/QGrpcChannel>
|
|
||||||
#endif
|
|
||||||
#include <QtGrpc/QGrpcHttp2Channel>
|
#include <QtGrpc/QGrpcHttp2Channel>
|
||||||
|
|
||||||
#include <server_proc_runner.h>
|
#include <server_proc_runner.h>
|
||||||
|
|
@ -24,8 +21,7 @@ protected:
|
||||||
enum Channel {
|
enum Channel {
|
||||||
NoChannels = 0x0,
|
NoChannels = 0x0,
|
||||||
Qt = 0x1,
|
Qt = 0x1,
|
||||||
Native = 0x2,
|
Ssl = 0x2,
|
||||||
Ssl = 0x4,
|
|
||||||
SslNoCredentials = 0x8,
|
SslNoCredentials = 0x8,
|
||||||
WithChannelDeadline = 0x10,
|
WithChannelDeadline = 0x10,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/qsystemdetection.h>
|
|
||||||
|
|
||||||
#include <QtGrpc/QGrpcCallOptions>
|
#include <QtGrpc/QGrpcCallOptions>
|
||||||
#include <QtGrpc/QGrpcClientInterceptorManager>
|
#include <QtGrpc/QGrpcClientInterceptorManager>
|
||||||
|
|
@ -17,10 +16,6 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
# include <grpcpp/security/credentials.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <interceptormocks.h>
|
#include <interceptormocks.h>
|
||||||
#include <message_latency_defs.h>
|
#include <message_latency_defs.h>
|
||||||
#include <server_proc_runner.h>
|
#include <server_proc_runner.h>
|
||||||
|
|
@ -36,7 +31,6 @@ public:
|
||||||
QtGrpcClientUnaryCallTest()
|
QtGrpcClientUnaryCallTest()
|
||||||
: GrpcClientTestBase(GrpcClientTestBase::Channels{
|
: GrpcClientTestBase(GrpcClientTestBase::Channels{
|
||||||
GrpcClientTestBase::Channel::Qt,
|
GrpcClientTestBase::Channel::Qt,
|
||||||
GrpcClientTestBase::Channel::Native,
|
|
||||||
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN32)
|
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN32)
|
||||||
GrpcClientTestBase::Channel::Ssl,
|
GrpcClientTestBase::Channel::Ssl,
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -260,8 +254,6 @@ void QtGrpcClientUnaryCallTest::Metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
QCOMPARE_EQ(clientErrorSpy.count(), 0);
|
QCOMPARE_EQ(clientErrorSpy.count(), 0);
|
||||||
if (channelType().testFlag(GrpcClientTestBase::Channel::Native))
|
|
||||||
QEXPECT_FAIL("", "Unimplemented in the reference gRPC channel", Abort);
|
|
||||||
QCOMPARE_EQ(serverHeaderCount, 1);
|
QCOMPARE_EQ(serverHeaderCount, 1);
|
||||||
QCOMPARE_EQ(clientReturnHeader, "valid_value"_ba);
|
QCOMPARE_EQ(clientReturnHeader, "valid_value"_ba);
|
||||||
}
|
}
|
||||||
|
|
@ -310,9 +302,6 @@ void QtGrpcClientUnaryCallTest::Deadline()
|
||||||
|
|
||||||
void QtGrpcClientUnaryCallTest::Interceptor()
|
void QtGrpcClientUnaryCallTest::Interceptor()
|
||||||
{
|
{
|
||||||
if (channelType().testFlag(GrpcClientTestBase::Channel::Native))
|
|
||||||
QSKIP("Unimplemented in the reference gRPC channel.");
|
|
||||||
|
|
||||||
constexpr QLatin1StringView clientMetadataKey = "client_header"_L1;
|
constexpr QLatin1StringView clientMetadataKey = "client_header"_L1;
|
||||||
constexpr QLatin1StringView serverMetadataKey = "server_header"_L1;
|
constexpr QLatin1StringView serverMetadataKey = "server_header"_L1;
|
||||||
constexpr QLatin1StringView interceptor1Id = "inter1"_L1;
|
constexpr QLatin1StringView interceptor1Id = "inter1"_L1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue