Introduce QGrpcCallOptions and QGrpcChannelOptions

Use the new classes to store call and channel options used to
create gRPC channels and perform gRPC calls.
Add QGrpcCallOptions parameter to call() and startStream() methods.
Change constructor parameter of QGrpcHttp2Channel and QGrpcChannel
to QGrpcChannelOptions that stores previous parameters used to
construct channel. Add additional deadline option to be able to
configure call timeout.

[ChangeLog] Add QGrpcCallOptions to store and process additional
call options.
[ChangeLog] Add QGrpcChannelOptions to store and process channel
options and default call options.

Task-number: QTBUG-111037
Change-Id: Icd92e95c036fb5b4c268907ab912fcf59ef9a69a
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Konrad Kujawa 2023-05-09 13:49:22 +02:00
parent b9e37c2648
commit 3b8b24c7e5
25 changed files with 628 additions and 231 deletions

View File

@ -6,7 +6,6 @@
#include <QGrpcHttp2Channel>
#include <QGrpcUserPasswordCredentials>
#include <QGrpcInsecureChannelCredentials>
#include <QDebug>
#include <QFile>
@ -45,10 +44,9 @@ void SimpleChatEngine::login(const QString &name, const QString &password)
QUrl url("http://localhost:65002");
// ![0]
std::shared_ptr<QAbstractGrpcChannel> channel(
new QGrpcHttp2Channel(url,
QGrpcUserPasswordCredentials(name, password.toUtf8())
| QGrpcInsecureChannelCredentials()));
Q_UNUSED(password);
QGrpcChannelOptions options(url);
std::shared_ptr<QAbstractGrpcChannel> channel(new QGrpcHttp2Channel(options));
// ![0]
m_client->attachChannel(channel);

View File

@ -36,9 +36,7 @@
The client application binds on the \c localhost with port
\c 50051:
\quotefromfile magic8ball/clientservice.cpp
\skipto QUrl url("http://localhost:50051", QUrl::StrictMode);
\printuntil | QGrpcInsecureCallCredentials()));
\snippet magic8ball/clientservice.cpp 0
And sends a request to the server part:
\quotefromfile magic8ball/clientservice.cpp

View File

@ -4,7 +4,6 @@
#include "clientservice.h"
#include <QGrpcHttp2Channel>
#include <QGrpcInsecureChannelCredentials>
using namespace qtgrpc::examples;
@ -16,10 +15,10 @@ ClientService::ClientService(QObject *parent) :
connect(m_client.get(), &ExampleService::Client::errorOccurred,
this, &ClientService::errorOccurred);
QUrl url("http://localhost:50051", QUrl::StrictMode);
m_client->attachChannel(std::make_shared<QGrpcHttp2Channel>(url,
QGrpcInsecureChannelCredentials()
| QGrpcInsecureCallCredentials()));
//! [0]
QGrpcChannelOptions channelOptions(QUrl("http://localhost:50051", QUrl::StrictMode));
m_client->attachChannel(std::make_shared<QGrpcHttp2Channel>(channelOptions));
//! [0]
}
void ClientService::errorOccurred()

View File

@ -14,6 +14,8 @@ qt_internal_add_module(Grpc
qgrpccredentials.h qgrpccredentials.cpp
qgrpcinsecurecredentials.h qgrpcinsecurecredentials.cpp
qgrpcuserpasswordcredentials.h qgrpcuserpasswordcredentials.cpp
qgrpccalloptions.h qgrpccalloptions.cpp
qgrpcchanneloptions.h qgrpcchanneloptions.cpp
qtgrpcglobal.h qtgrpcglobal_p.h qtgrpcglobal.cpp
GENERATE_CPP_EXPORTS
LIBRARIES

View File

@ -20,11 +20,12 @@ QT_BEGIN_NAMESPACE
/*!
\fn virtual QGrpcStatus QAbstractGrpcChannel::call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args, QByteArray &ret) = 0
QByteArrayView args, QByteArray &ret, const QGrpcCallOptions &options = QGrpcCallOptions()) = 0
This pure virtual function synchronously calls the RPC method concatenated
from the \a method and \a service parameters with the given \a args
and writes the result to the output parameter \a ret.
Uses \a options argument to set additional parameter for the call.
You may reimplement this function in a subclass to define your own call
mechanism behavior. QGrpcChannel or QGrpcHttp2Channel, which are full
@ -33,12 +34,12 @@ QT_BEGIN_NAMESPACE
/*!
\fn virtual std::shared_ptr<QGrpcCallReply> QAbstractGrpcChannel::call(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView args) = 0
QLatin1StringView service, QByteArrayView args, const QGrpcCallOptions &options = QGrpcCallOptions()) = 0
This pure virtual function asynchronously calls the RPC method combined
with the \a method and \a service parameters with the given \a args
and returns an asynchronous response in the form of QGrpcCallReply.
Uses \a options argument to set additional parameter for the call.
You may reimplement this function in a subclass to define your own call
mechanism behavior. QGrpcChannel or QGrpcHttp2Channel, which are full
@ -47,14 +48,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn virtual std::shared_ptr<QGrpcStream> QAbstractGrpcChannel::startStream(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView arg) = 0
QLatin1StringView service, QByteArrayView arg, const QGrpcCallOptions &options = QGrpcCallOptions()) = 0
This pure virtual function 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.
Returns a shared pointer to the QGrpcStream.
Returns a shared pointer to the QGrpcStream. Uses \a options argument
to set additional parameter for the stream.
You may reimplement this function in a subclass to define your own stream
mechanism behavior. QGrpcChannel or QGrpcHttp2Channel, which are full

View File

@ -8,6 +8,7 @@
#include <QtCore/QString>
#include <QtCore/QThread>
#include <QtCore/qbytearray.h>
#include <QtGrpc/qgrpccalloptions.h>
#include <QtGrpc/qgrpccredentials.h>
#include <QtGrpc/qgrpcstatus.h>
#include <QtGrpc/qtgrpcglobal.h>
@ -26,13 +27,14 @@ class Q_GRPC_EXPORT QAbstractGrpcChannel
{
public:
virtual QGrpcStatus call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args, QByteArray &ret) = 0;
virtual std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView args) = 0;
virtual std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView arg) = 0;
QByteArrayView args, QByteArray &ret,
const QGrpcCallOptions &options = QGrpcCallOptions()) = 0;
virtual std::shared_ptr<QGrpcCallReply> call(
QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
const QGrpcCallOptions &options = QGrpcCallOptions()) = 0;
virtual std::shared_ptr<QGrpcStream> startStream(
QLatin1StringView method, QLatin1StringView service, QByteArrayView arg,
const QGrpcCallOptions &options = QGrpcCallOptions()) = 0;
virtual std::shared_ptr<QAbstractProtobufSerializer> serializer() const = 0;
protected:

View File

@ -45,26 +45,29 @@ static QString threadSafetyWarning(QLatin1StringView methodName)
/*!
\fn template <typename ParamType> QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method,
const QProtobufMessage &arg)
const QProtobufMessage &arg, const QGrpcCallOptions &options);
Synchronously calls the given \a method of this service client,
with argument \a arg.
Uses \a options argument to set additional parameter for the call.
*/
/*!
\fn template <typename ParamType, typename ReturnType> QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method,
const QProtobufMessage &arg, ReturnType &ret)
const QProtobufMessage &arg, ReturnType &ret, const QGrpcCallOptions &options);
Synchronously calls the given \a method of this service client,
with argument \a arg and fills \a ret with gRPC reply.
Uses \a options argument to set additional parameter for the call.
*/
/*!
\fn template <typename ParamType> QSharedPointer<QGrpcStream> QAbstractGrpcClient::startStream(QLatin1StringView method,
const QProtobufMessage &arg)
const QProtobufMessage &arg, const QGrpcCallOptions &options);
Streams messages from the server stream \a method with the message
argument \a arg to the attached channel.
Uses \a options argument to set additional parameter for the call.
*/
class QAbstractGrpcClientPrivate : public QObjectPrivate
@ -114,7 +117,8 @@ void QAbstractGrpcClient::attachChannel(const std::shared_ptr<QAbstractGrpcChann
stream->abort();
}
QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method, QByteArrayView arg, QByteArray &ret)
QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method, QByteArrayView arg, QByteArray &ret,
const QGrpcCallOptions &options)
{
QGrpcStatus callStatus{ QGrpcStatus::Unknown };
if (thread() != QThread::currentThread()) {
@ -126,8 +130,9 @@ QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method, QByteArrayView a
}
Q_D(QAbstractGrpcClient);
callStatus = d->channel ? d->channel->call(method, QLatin1StringView(d->service), arg, ret)
: QGrpcStatus{ QGrpcStatus::Unknown, "No channel(s) attached."_L1 };
callStatus = d->channel
? d->channel->call(method, QLatin1StringView(d->service), arg, ret, options)
: QGrpcStatus{ QGrpcStatus::Unknown, "No channel(s) attached."_L1 };
if (callStatus != QGrpcStatus::Ok)
emit errorOccurred(callStatus);
@ -136,7 +141,8 @@ QGrpcStatus QAbstractGrpcClient::call(QLatin1StringView method, QByteArrayView a
}
std::shared_ptr<QGrpcCallReply> QAbstractGrpcClient::call(QLatin1StringView method,
QByteArrayView arg)
QByteArrayView arg,
const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply;
if (thread() != QThread::currentThread()) {
@ -149,12 +155,13 @@ std::shared_ptr<QGrpcCallReply> QAbstractGrpcClient::call(QLatin1StringView meth
Q_D(QAbstractGrpcClient);
if (d->channel) {
reply = d->channel->call(method, QLatin1StringView(d->service), arg);
reply = d->channel->call(method, QLatin1StringView(d->service), arg, options);
auto errorConnection = std::make_shared<QMetaObject::Connection>();
*errorConnection =
connect(reply.get(), &QGrpcCallReply::errorOccurred, this,
[this](const QGrpcStatus &status) { emit errorOccurred(status); });
*errorConnection = connect(reply.get(), &QGrpcCallReply::errorOccurred, this,
[this](const QGrpcStatus &status) {
emit errorOccurred(status);
});
} else {
emit errorOccurred({ QGrpcStatus::Unknown, "No channel(s) attached."_L1 });
}
@ -163,7 +170,8 @@ std::shared_ptr<QGrpcCallReply> QAbstractGrpcClient::call(QLatin1StringView meth
}
std::shared_ptr<QGrpcStream> QAbstractGrpcClient::startStream(QLatin1StringView method,
QByteArrayView arg)
QByteArrayView arg,
const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcStream> grpcStream;
@ -181,7 +189,7 @@ std::shared_ptr<QGrpcStream> QAbstractGrpcClient::startStream(QLatin1StringView
auto errorConnection = std::make_shared<QMetaObject::Connection>();
*errorConnection = connect(grpcStream.get(), &QGrpcStream::errorOccurred, this,
[this, grpcStream](const QGrpcStatus &status) {
[this, grpcStream, &options](const QGrpcStatus &status) {
Q_D(QAbstractGrpcClient);
qGrpcWarning()
<< grpcStream->method() << "call" << d->service
@ -190,8 +198,9 @@ std::shared_ptr<QGrpcStream> QAbstractGrpcClient::startStream(QLatin1StringView
// TODO: Make timeout configurable from channel settings
QTimer::singleShot(1000, this,
[this, method = grpcStream->method(),
arg = grpcStream->arg()] {
this->startStream(method, arg);
arg = grpcStream->arg(), &options] {
this->startStream(method, arg,
options);
});
});

View File

@ -38,7 +38,8 @@ protected:
~QAbstractGrpcClient() override;
template <typename ParamType, typename ReturnType>
QGrpcStatus call(QLatin1StringView method, const QProtobufMessage &arg, ReturnType &ret)
QGrpcStatus call(QLatin1StringView method, const QProtobufMessage &arg, ReturnType &ret,
const QGrpcCallOptions &options)
{
using namespace Qt::StringLiterals;
QGrpcStatus status{ QGrpcStatus::Unknown,
@ -47,7 +48,7 @@ protected:
std::optional<QByteArray> argData = trySerialize<ParamType>(arg);
if (argData) {
QByteArray retData;
status = call(method, *argData, retData);
status = call(method, *argData, retData, options);
if (status == QGrpcStatus::StatusCode::Ok)
status = tryDeserialize(ret, retData);
}
@ -55,29 +56,34 @@ protected:
}
template <typename ParamType>
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, const QProtobufMessage &arg)
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, const QProtobufMessage &arg,
const QGrpcCallOptions &options)
{
std::optional<QByteArray> argData = trySerialize<ParamType>(arg);
if (!argData)
return {};
return call(method, *argData);
return call(method, *argData, options);
}
template <typename ParamType>
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, const QProtobufMessage &arg)
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, const QProtobufMessage &arg,
const QGrpcCallOptions &options)
{
std::optional<QByteArray> argData = trySerialize<ParamType>(arg);
if (!argData)
return {};
return startStream(method, *argData);
return startStream(method, *argData, options);
}
private:
QGrpcStatus call(QLatin1StringView method, QByteArrayView arg, QByteArray &ret);
QGrpcStatus call(QLatin1StringView method, QByteArrayView arg, QByteArray &ret,
const QGrpcCallOptions &options);
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, QByteArrayView arg);
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, QByteArrayView arg,
const QGrpcCallOptions &options);
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, QByteArrayView arg);
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, QByteArrayView arg,
const QGrpcCallOptions &options);
template <typename ReturnType>
QGrpcStatus tryDeserialize(ReturnType *ret, QByteArrayView retData)
@ -96,8 +102,8 @@ private:
using namespace Qt::StringLiterals;
auto _serializer = serializer();
if (_serializer == nullptr) {
Q_EMIT errorOccurred(
{ QGrpcStatus::Unknown, "Serializing failed. Serializer is not ready."_L1 });
Q_EMIT errorOccurred({ QGrpcStatus::Unknown,
"Serializing failed. Serializer is not ready."_L1 });
return std::nullopt;
}
return _serializer->serialize<ParamType>(&arg);

View File

@ -0,0 +1,120 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtgrpcglobal_p.h>
#include "qgrpccalloptions.h"
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
/*!
\class QGrpcCallOptions
\inmodule QtGrpc
\brief The QGrpcCallOptions is an storage class used by set additional call options.
QGrpcCallOptions provides a set of functions to access the call options
that are used by gRPC channels to communicate with the services.
*/
struct QGrpcCallOptionsPrivate
{
public:
QGrpcCallOptionsPrivate() : credentials(nullptr) { }
std::optional<QUrl> host;
std::optional<std::chrono::milliseconds> deadline;
std::shared_ptr<QGrpcCallCredentials> credentials;
std::optional<qint64> maxRetryAttempts;
};
/*!
Constructs an empty QGrpcCallOptions object.
*/
QGrpcCallOptions::QGrpcCallOptions() : dPtr(std::make_unique<QGrpcCallOptionsPrivate>())
{
}
/*!
Destroys the QGrpcCallOptions object.
*/
QGrpcCallOptions::~QGrpcCallOptions() = default;
/*!
Construct a copy of QGrpcCallOptions with \a other object.
*/
QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other)
: dPtr(std::make_unique<QGrpcCallOptionsPrivate>(*other.dPtr))
{
}
/*!
Assigns \a other to this QGrpcCallOptions and returns a reference to this
QGrpcCallOptions.
*/
QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
{
*dPtr = *other.dPtr;
return *this;
}
/*!
Sets deadline value with \a deadline and returns updated QGrpcCallOptions object.
*/
QGrpcCallOptions &QGrpcCallOptions::withDeadline(std::chrono::milliseconds deadline)
{
dPtr->deadline = deadline;
return *this;
}
/*!
Sets call credentials with \a credentials and returns updated QGrpcCallOptions object.
*/
QGrpcCallOptions &QGrpcCallOptions::withCredentials(
std::shared_ptr<QGrpcCallCredentials> credentials)
{
dPtr->credentials = credentials;
return *this;
}
/*!
Sets maximum retry attempts value with \a maxRetryAttempts and returns updated QGrpcCallOptions object.
*/
QGrpcCallOptions &QGrpcCallOptions::withMaxRetryAttempts(qint64 maxRetryAttempts)
{
dPtr->maxRetryAttempts = maxRetryAttempts;
return *this;
}
/*!
Returns deadline value for a call.
If value was not set returns empty std::optional.
*/
std::optional<std::chrono::milliseconds> QGrpcCallOptions::deadline() const
{
return dPtr->deadline;
}
/*!
Returns credentials for a call.
If value was not set returns empty std::optional.
*/
std::optional<QGrpcCredentialMap> QGrpcCallOptions::credentials() const
{
return dPtr->credentials ? (*dPtr->credentials)() : std::optional<QGrpcCredentialMap>();
}
/*!
Returns maximum retry attempts value for a call.
If value was not set returns empty std::optional.
*/
std::optional<qint64> QGrpcCallOptions::maxRetryAttempts() const
{
return dPtr->maxRetryAttempts;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,42 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QGRPCALLOPTIONS_H
#define QGRPCALLOPTIONS_H
#include <QtCore/QUrl>
#include <QtGrpc/QGrpcCallCredentials>
#include <QtGrpc/qtgrpcglobal.h>
#include <chrono>
#include <memory>
#include <optional>
QT_BEGIN_NAMESPACE
struct QGrpcCallOptionsPrivate;
class Q_GRPC_EXPORT QGrpcCallOptions final
{
public:
QGrpcCallOptions();
~QGrpcCallOptions();
QGrpcCallOptions(const QGrpcCallOptions &other);
QGrpcCallOptions &operator=(const QGrpcCallOptions &other);
QGrpcCallOptions &withDeadline(std::chrono::milliseconds deadline);
QGrpcCallOptions &withCredentials(std::shared_ptr<QGrpcCallCredentials> credentials);
QGrpcCallOptions &withMaxRetryAttempts(qint64 maxRetryAttempts);
std::optional<std::chrono::milliseconds> deadline() const;
std::optional<QGrpcCredentialMap> credentials() const;
std::optional<qint64> maxRetryAttempts() const;
private:
std::unique_ptr<QGrpcCallOptionsPrivate> dPtr;
};
QT_END_NAMESPACE
#endif // QGRPCALLOPTIONS_H

View File

@ -180,39 +180,38 @@ void QGrpcChannelCall::waitForFinished(const QDeadlineTimer &deadline)
thread->wait(deadline);
}
QGrpcChannelPrivate::QGrpcChannelPrivate(const QUrl &url,
QGrpcChannel::NativeGrpcChannelCredentials credentialsType,
const QStringList &credentialsList)
QGrpcChannelPrivate::QGrpcChannelPrivate(const QGrpcChannelOptions &options,
QGrpcChannel::NativeGrpcChannelCredentials credentialsType)
{
switch (credentialsType) {
case QGrpcChannel::InsecureChannelCredentials:
m_credentials = grpc::InsecureChannelCredentials();
m_channel = grpc::CreateChannel(url.toString().toStdString(), m_credentials);
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
break;
case QGrpcChannel::GoogleDefaultCredentials:
m_credentials = grpc::GoogleDefaultCredentials();
m_channel = grpc::CreateChannel(url.toString().toStdString(), m_credentials);
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
break;
case QGrpcChannel::SslDefaultCredentials:
if (credentialsList.size() < 3) {
m_credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
} else {
if (auto maybeCredentialList = options.credentialList()) {
grpc::SslCredentialsOptions options;
options.pem_root_certs = credentialsList[0].toStdString();
options.pem_private_key = credentialsList[1].toStdString();
options.pem_cert_chain = credentialsList[2].toStdString();
options.pem_root_certs = (*maybeCredentialList)[0].toStdString();
options.pem_private_key = (*maybeCredentialList)[1].toStdString();
options.pem_cert_chain = (*maybeCredentialList)[2].toStdString();
m_credentials = grpc::SslCredentials(options);
} else {
m_credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
}
m_channel = grpc::CreateChannel(url.toString().toStdString(), m_credentials);
m_channel = grpc::CreateChannel(options.host().toString().toStdString(), m_credentials);
break;
}
}
QGrpcChannelPrivate::~QGrpcChannelPrivate() = default;
std::shared_ptr<QGrpcCallReply> QGrpcChannelPrivate::call(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView args)
std::shared_ptr<QGrpcCallReply> QGrpcChannelPrivate::call(
QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
[[maybe_unused]] const QGrpcCallOptions &options)
{
const QByteArray rpcName = buildRpcName(service, method);
std::shared_ptr<QGrpcCallReply> reply(new QGrpcCallReply(serializer()));
@ -248,21 +247,22 @@ std::shared_ptr<QGrpcCallReply> QGrpcChannelPrivate::call(QLatin1StringView meth
}
QGrpcStatus QGrpcChannelPrivate::call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args, QByteArray &ret)
QByteArrayView args, QByteArray &ret,
const QGrpcCallOptions &options)
{
const QByteArray rpcName = buildRpcName(service, method);
QGrpcChannelCall call(m_channel.get(), QLatin1StringView(rpcName), args);
call.start();
call.waitForFinished();
options.deadline() ? call.waitForFinished(*options.deadline()) : call.waitForFinished();
ret = call.response;
return call.status;
}
std::shared_ptr<QGrpcStream> QGrpcChannelPrivate::startStream(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView arg)
std::shared_ptr<QGrpcStream> QGrpcChannelPrivate::startStream(
QLatin1StringView method, QLatin1StringView service, QByteArrayView arg,
[[maybe_unused]] const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcStream> stream(new QGrpcStream(method, arg, serializer()));
const QByteArray rpcName = buildRpcName(service, stream->method());
@ -315,22 +315,11 @@ std::shared_ptr<QAbstractProtobufSerializer> QGrpcChannelPrivate::serializer() c
}
/*!
Constructs a gRPC channel, with \a url, \a credentialsType,
and \a credentialsList object.
Constructs a gRPC channel, with \a options and \a credentialsType.
*/
QGrpcChannel::QGrpcChannel(const QUrl &url, NativeGrpcChannelCredentials credentialsType,
const QStringList &credentialsList)
: QAbstractGrpcChannel(),
dPtr(std::make_unique<QGrpcChannelPrivate>(url, credentialsType, credentialsList))
{
}
/*!
Constructs a gRPC channel, with \a url, \a credentialsType and
an empty credentials list.
*/
QGrpcChannel::QGrpcChannel(const QUrl &url, NativeGrpcChannelCredentials credentialsType)
: QGrpcChannel(std::move(url), credentialsType, QStringList())
QGrpcChannel::QGrpcChannel(const QGrpcChannelOptions &options,
NativeGrpcChannelCredentials credentialsType)
: QAbstractGrpcChannel(), dPtr(std::make_unique<QGrpcChannelPrivate>(options, credentialsType))
{
}
@ -344,11 +333,13 @@ QGrpcChannel::~QGrpcChannel() = default;
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a args argument.
Uses \a options argument to set additional parameter for the call.
*/
QGrpcStatus QGrpcChannel::call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args, QByteArray &ret)
QByteArrayView args, QByteArray &ret,
const QGrpcCallOptions &options)
{
return dPtr->call(method, service, args, ret);
return dPtr->call(method, service, args, ret, options);
}
/*!
@ -356,13 +347,15 @@ QGrpcStatus QGrpcChannel::call(QLatin1StringView method, QLatin1StringView servi
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a args argument.
Uses \a options argument to set additional parameter for the call.
The method can emit QGrpcCallReply::finished() and QGrpcCallReply::errorOccurred()
signals on a QGrpcCallReply returned object.
*/
std::shared_ptr<QGrpcCallReply> QGrpcChannel::call(QLatin1StringView method,
QLatin1StringView service, QByteArrayView args)
QLatin1StringView service, QByteArrayView args,
const QGrpcCallOptions &options)
{
return dPtr->call(method, service, args);
return dPtr->call(method, service, args, options);
}
/*!
@ -371,15 +364,17 @@ std::shared_ptr<QGrpcCallReply> QGrpcChannel::call(QLatin1StringView method,
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a arg argument.
Returns a shared pointer to the QGrpcStream.
Uses \a options argument to set additional parameter for the stream.
Calls QGrpcStream::updateData() when the stream receives data from the server.
The method may emit QGrpcStream::errorOccurred() when the stream has terminated with an error.
*/
std::shared_ptr<QGrpcStream> QGrpcChannel::startStream(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView arg)
QByteArrayView arg,
const QGrpcCallOptions &options)
{
return dPtr->startStream(method, service, arg);
return dPtr->startStream(method, service, arg, options);
}
/*!

View File

@ -8,6 +8,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QUrl>
#include <QtGrpc/qabstractgrpcclient.h>
#include <QtGrpc/qgrpcchanneloptions.h>
#include <QtGrpc/qtgrpcglobal.h>
#include <memory>
@ -26,17 +27,20 @@ public:
SslDefaultCredentials,
};
explicit QGrpcChannel(const QUrl &name, NativeGrpcChannelCredentials credentialsType,
const QStringList &credentialsList);
explicit QGrpcChannel(const QUrl &name, NativeGrpcChannelCredentials credentialsType);
explicit QGrpcChannel(const QGrpcChannelOptions &options,
NativeGrpcChannelCredentials credentialsType);
~QGrpcChannel() override;
QGrpcStatus call(QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
QByteArray &ret) override;
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args) override;
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, QLatin1StringView service,
QByteArrayView arg) override;
QByteArray &ret,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QGrpcCallReply> call(
QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QGrpcStream> startStream(
QLatin1StringView method, QLatin1StringView service, QByteArrayView arg,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QAbstractProtobufSerializer> serializer() const override;
private:

View File

@ -92,17 +92,16 @@ struct QGrpcChannelPrivate
std::shared_ptr<grpc::Channel> m_channel;
std::shared_ptr<grpc::ChannelCredentials> m_credentials;
explicit QGrpcChannelPrivate(const QUrl &url,
QGrpcChannel::NativeGrpcChannelCredentials credentialsType,
const QStringList &credentialsList);
explicit QGrpcChannelPrivate(const QGrpcChannelOptions &options,
QGrpcChannel::NativeGrpcChannelCredentials credentialsType);
~QGrpcChannelPrivate();
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args);
QByteArrayView args, const QGrpcCallOptions &options);
QGrpcStatus call(QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
QByteArray &ret);
QByteArray &ret, const QGrpcCallOptions &options);
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, QLatin1StringView service,
QByteArrayView arg);
QByteArrayView arg, const QGrpcCallOptions &options);
std::shared_ptr<QAbstractProtobufSerializer> serializer() const;
};

View File

@ -0,0 +1,164 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtgrpcglobal_p.h>
#include "qgrpcchanneloptions.h"
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
/*!
\class QGrpcChannelOptions
\inmodule QtGrpc
\brief The QGrpcChannelOptions is an storage class used to set additional channel options.
QGrpcChannelOptions provides a set of functions to set and access the channel and default call
options that are used by gRPC channels to communicate with the services.
*/
struct QGrpcChannelOptionsPrivate
{
public:
QGrpcChannelOptionsPrivate(const QUrl &_host) : host(_host), credentials(nullptr) { }
QUrl host;
std::optional<std::chrono::milliseconds> deadline;
std::shared_ptr<QGrpcChannelCredentials> credentials;
std::optional<QStringList> credentialList;
#if QT_CONFIG(ssl)
std::optional<QSslConfiguration> sslConfiguration;
#endif
};
/*!
Constructs an QGrpcChannelOptions object with \a host value.
*/
QGrpcChannelOptions::QGrpcChannelOptions(const QUrl &host)
: dPtr(std::make_unique<QGrpcChannelOptionsPrivate>(host))
{
}
/*!
Construct a copy of QGrpcChannelOptions with \a other object.
*/
QGrpcChannelOptions::QGrpcChannelOptions(const QGrpcChannelOptions &other)
: dPtr(std::make_unique<QGrpcChannelOptionsPrivate>(*other.dPtr))
{
}
/*!
Assigns \a other to this QGrpcChannelOptions and returns a reference to this
QGrpcChannelOptions.
*/
QGrpcChannelOptions &QGrpcChannelOptions::operator=(const QGrpcChannelOptions &other)
{
*dPtr = *other.dPtr;
return *this;
}
/*!
Destroys the QGrpcChannelOptions object.
*/
QGrpcChannelOptions::~QGrpcChannelOptions() = default;
/*!
Sets host value with \a host and returns updated QGrpcChannelOptions object.
*/
QGrpcChannelOptions &QGrpcChannelOptions::withHost(const QUrl &host)
{
dPtr->host = host;
return *this;
}
/*!
Sets deadline value with \a deadline and returns updated QGrpcChannelOptions object.
*/
QGrpcChannelOptions &QGrpcChannelOptions::withDeadline(std::chrono::milliseconds deadline)
{
dPtr->deadline = deadline;
return *this;
}
/*!
Sets channel credentials with \a credentials and returns updated QGrpcChannelOptions object.
*/
QGrpcChannelOptions &QGrpcChannelOptions::withCredentials(
std::shared_ptr<QGrpcChannelCredentials> credentials)
{
dPtr->credentials = credentials;
return *this;
}
/*!
Sets channel credential list with \a credentialList and returns updated QGrpcChannelOptions object.
*/
QGrpcChannelOptions &QGrpcChannelOptions::withCredentialList(const QStringList &credentialList)
{
dPtr->credentialList = credentialList;
return *this;
}
/*!
Returns deadline value for every call on the channel.
If value was not set returns empty std::optional.
*/
std::optional<std::chrono::milliseconds> QGrpcChannelOptions::deadline() const
{
return dPtr->deadline;
}
/*!
Returns host value for every call on the channel.
*/
QUrl QGrpcChannelOptions::host() const
{
return dPtr->host;
}
/*!
Returns credentials for the channel.
If value was not set returns empty std::optional.
*/
std::optional<QGrpcCredentialMap> QGrpcChannelOptions::credentials() const
{
return dPtr->credentials ? dPtr->credentials->channelCredentials()
: std::optional<QGrpcCredentialMap>();
}
/*!
Returns credential list for the channel.
If value was not set returns empty std::optional.
*/
std::optional<QStringList> QGrpcChannelOptions::credentialList() const
{
return dPtr->credentialList;
}
#if QT_CONFIG(ssl)
/*!
Sets SSL configuration with \a sslConfiguration and returns updated QGrpcChannelOptions object.
*/
QGrpcChannelOptions &QGrpcChannelOptions::withSslConfiguration(
const QSslConfiguration &sslConfiguration)
{
dPtr->sslConfiguration = sslConfiguration;
return *this;
}
/*!
Returns SSL configuration for the channel.
If value was not set returns empty std::optional.
*/
std::optional<QSslConfiguration> QGrpcChannelOptions::sslConfiguration() const
{
return dPtr->sslConfiguration;
}
#endif
QT_END_NAMESPACE

View File

@ -0,0 +1,53 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QGRPCHANNELOPTIONS_H
#define QGRPCHANNELOPTIONS_H
#include <QtCore/QUrl>
#include <QtGrpc/QGrpcChannelCredentials>
#include <QtGrpc/qtgrpcglobal.h>
#if QT_CONFIG(ssl)
# include <QtNetwork/QSslConfiguration>
#endif
#include <chrono>
#include <memory>
#include <optional>
QT_BEGIN_NAMESPACE
class QSslConfiguration;
struct QGrpcChannelOptionsPrivate;
class Q_GRPC_EXPORT QGrpcChannelOptions final
{
public:
explicit QGrpcChannelOptions(const QUrl &host);
~QGrpcChannelOptions();
QGrpcChannelOptions(const QGrpcChannelOptions &other);
QGrpcChannelOptions &operator=(const QGrpcChannelOptions &other);
QGrpcChannelOptions &withHost(const QUrl &host);
QGrpcChannelOptions &withDeadline(std::chrono::milliseconds deadline);
QGrpcChannelOptions &withCredentials(std::shared_ptr<QGrpcChannelCredentials> credentials);
QGrpcChannelOptions &withCredentialList(const QStringList &credentialList);
QUrl host() const;
std::optional<std::chrono::milliseconds> deadline() const;
std::optional<QGrpcCredentialMap> credentials() const;
std::optional<QStringList> credentialList() const;
#if QT_CONFIG(ssl)
QGrpcChannelOptions &withSslConfiguration(const QSslConfiguration &sslConfiguration);
std::optional<QSslConfiguration> sslConfiguration() const;
#endif
private:
std::unique_ptr<QGrpcChannelOptionsPrivate> dPtr;
};
QT_END_NAMESPACE
#endif // QGRPCHANNELOPTIONS_H

View File

@ -94,9 +94,8 @@ struct QGrpcHttp2ChannelPrivate
QByteArray container;
};
QUrl url;
QNetworkAccessManager nm;
std::unique_ptr<QAbstractGrpcCredentials> credentials;
QGrpcChannelOptions channelOptions;
#if QT_CONFIG(ssl)
QSslConfiguration sslConfig;
#endif
@ -104,9 +103,9 @@ struct QGrpcHttp2ChannelPrivate
QObject lambdaContext;
QNetworkReply *post(QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
bool stream = false)
const QGrpcCallOptions &callOptions, bool stream = false)
{
QUrl callUrl = url;
QUrl callUrl = channelOptions.host();
callUrl.setPath("/%1/%2"_L1.arg(service, method));
qGrpcDebug() << "Service call url:" << callUrl;
@ -118,9 +117,10 @@ struct QGrpcHttp2ChannelPrivate
#if QT_CONFIG(ssl)
request.setSslConfiguration(sslConfig);
#endif
for (const auto &[key, value] : credentials->callCredentials().toStdMap())
request.setRawHeader(key, value.toString().toUtf8());
if (const auto credentials = callOptions.credentials()) {
for (const auto &[key, value] : credentials->toStdMap())
request.setRawHeader(key, value.toString().toUtf8());
}
request.setAttribute(QNetworkRequest::Http2DirectAttribute, true);
QByteArray msg(GrpcMessageSizeHeaderSize, '\0');
@ -175,22 +175,22 @@ struct QGrpcHttp2ChannelPrivate
return networkReply->readAll().mid(GrpcMessageSizeHeaderSize);
}
QGrpcHttp2ChannelPrivate(const QUrl &_url,
std::unique_ptr<QAbstractGrpcCredentials> _credentials)
: url(_url), credentials(std::move(_credentials))
QGrpcHttp2ChannelPrivate(const QGrpcChannelOptions &options) : channelOptions(options)
{
#if QT_CONFIG(ssl)
if (url.scheme() == "https"_L1) {
if (channelOptions.host().scheme() == "https"_L1) {
// HTTPS connection requested but not ssl configuration provided.
Q_ASSERT(credentials->channelCredentials().contains(SslConfigCredential));
sslConfig = credentials->channelCredentials()
.value(SslConfigCredential)
.value<QSslConfiguration>();
} else if (url.scheme().isEmpty()) {
url.setScheme("http"_L1);
Q_ASSERT(channelOptions.sslConfiguration());
sslConfig = *channelOptions.sslConfiguration();
} else if (channelOptions.host().scheme().isEmpty()) {
auto tmpHost = channelOptions.host();
tmpHost.setScheme("http"_L1);
channelOptions.withHost(tmpHost);
}
#else
url.setScheme("http"_L1);
auto tmpHost = channelOptions.host();
tmpHost.setScheme("http"_L1);
channelOptions.withHost(tmpHost);
#endif
}
@ -202,13 +202,10 @@ struct QGrpcHttp2ChannelPrivate
};
/*!
QGrpcHttp2Channel constructs QGrpcHttp2Channel with \a url used to
establish channel connections and \a credentials.
QGrpcHttp2Channel constructs QGrpcHttp2Channel with \a options.
*/
QGrpcHttp2Channel::QGrpcHttp2Channel(const QUrl &url,
std::unique_ptr<QAbstractGrpcCredentials> credentials)
: QAbstractGrpcChannel(),
dPtr(std::make_unique<QGrpcHttp2ChannelPrivate>(url, std::move(credentials)))
QGrpcHttp2Channel::QGrpcHttp2Channel(const QGrpcChannelOptions &options)
: QAbstractGrpcChannel(), dPtr(std::make_unique<QGrpcHttp2ChannelPrivate>(options))
{
}
@ -222,13 +219,15 @@ QGrpcHttp2Channel::~QGrpcHttp2Channel() = default;
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a args argument.
Uses \a options argument to set additional parameter for the call.
*/
QGrpcStatus QGrpcHttp2Channel::call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args, QByteArray &ret)
QByteArrayView args, QByteArray &ret,
const QGrpcCallOptions &options)
{
QEventLoop loop;
QNetworkReply *networkReply = dPtr->post(method, service, args);
QNetworkReply *networkReply = dPtr->post(method, service, args, options);
QObject::connect(networkReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
// If reply was finished in same stack it doesn't make sense to start event loop
@ -248,17 +247,19 @@ QGrpcStatus QGrpcHttp2Channel::call(QLatin1StringView method, QLatin1StringView
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a args argument.
Uses \a options argument to set additional parameter for the call.
The method can emit QGrpcCallReply::finished() and QGrpcCallReply::errorOccurred()
signals on a QGrpcCallReply returned object.
*/
std::shared_ptr<QGrpcCallReply> QGrpcHttp2Channel::call(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView args)
QByteArrayView args,
const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply(new QGrpcCallReply(serializer()),
[](QGrpcCallReply *reply) { reply->deleteLater(); });
QNetworkReply *networkReply = dPtr->post(method, service, args);
QNetworkReply *networkReply = dPtr->post(method, service, args, options);
auto connection = std::make_shared<QMetaObject::Connection>();
auto abortConnection = std::make_shared<QMetaObject::Connection>();
@ -302,16 +303,18 @@ std::shared_ptr<QGrpcCallReply> QGrpcHttp2Channel::call(QLatin1StringView method
The RPC method name is constructed by concatenating the \a method
and \a service parameters and called with the \a arg argument.
Returns a shared pointer to the QGrpcStream.
Returns a shared pointer to the QGrpcStream. Uses \a options argument
to set additional parameter for the stream.
Calls QGrpcStream::updateData() when the stream receives data from the server.
The method may emit QGrpcStream::errorOccurred() when the stream has terminated with an error.
*/
std::shared_ptr<QGrpcStream> QGrpcHttp2Channel::startStream(QLatin1StringView method,
QLatin1StringView service,
QByteArrayView arg)
QByteArrayView arg,
const QGrpcCallOptions &options)
{
QNetworkReply *networkReply = dPtr->post(method, service, arg, true);
QNetworkReply *networkReply = dPtr->post(method, service, arg, options, true);
std::shared_ptr<QGrpcStream> grpcStream(new QGrpcStream(method, arg, serializer()));
auto finishConnection = std::make_shared<QMetaObject::Connection>();

View File

@ -7,6 +7,7 @@
#include <QtCore/QUrl>
#include <QtGrpc/qabstractgrpcchannel.h>
#include <QtGrpc/qgrpcchanneloptions.h>
#include <memory>
@ -18,16 +19,18 @@ struct QGrpcHttp2ChannelPrivate;
class Q_GRPC_EXPORT QGrpcHttp2Channel final : public QAbstractGrpcChannel
{
public:
explicit QGrpcHttp2Channel(const QUrl &url,
std::unique_ptr<QAbstractGrpcCredentials> credentials);
explicit QGrpcHttp2Channel(const QGrpcChannelOptions &options);
~QGrpcHttp2Channel() override;
QGrpcStatus call(QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
QByteArray &ret) override;
std::shared_ptr<QGrpcCallReply> call(QLatin1StringView method, QLatin1StringView service,
QByteArrayView args) override;
std::shared_ptr<QGrpcStream> startStream(QLatin1StringView method, QLatin1StringView service,
QByteArrayView arg) override;
QByteArray &ret,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QGrpcCallReply> call(
QLatin1StringView method, QLatin1StringView service, QByteArrayView args,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QGrpcStream> startStream(
QLatin1StringView method, QLatin1StringView service, QByteArrayView arg,
const QGrpcCallOptions &options = QGrpcCallOptions()) override;
std::shared_ptr<QAbstractProtobufSerializer> serializer() const override;
private:

View File

@ -14,19 +14,21 @@ const char *GrpcTemplates::ChildClassDeclarationTemplate()
const char *GrpcTemplates::ClientMethodDeclarationSyncTemplate()
{
return "QGrpcStatus $method_name$(const $param_type$ &$param_name$, "
"$return_type$ *$return_name$);\n";
"$return_type$ *$return_name$, const QGrpcCallOptions &options = {});\n";
}
const char *GrpcTemplates::ClientMethodDeclarationAsyncTemplate()
{
return "std::shared_ptr<QGrpcCallReply> $method_name$(const $param_type$ &$param_name$);\n";
return "std::shared_ptr<QGrpcCallReply> $method_name$(const $param_type$ &$param_name$, const "
"QGrpcCallOptions &options = {});\n";
}
const char *GrpcTemplates::ClientMethodDeclarationAsync2Template()
{
return "Q_INVOKABLE void $method_name$(const $param_type$ &$param_name$, const QObject "
"*context, "
"const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback);\n";
"const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const "
"QGrpcCallOptions &options = {});\n";
}
const char *GrpcTemplates::ClientMethodDeclarationQmlTemplate()
@ -59,28 +61,30 @@ const char *GrpcTemplates::ClientConstructorDefinitionTemplate()
const char *GrpcTemplates::ClientMethodDefinitionSyncTemplate()
{
return "QGrpcStatus $classname$::$method_name$(const $param_type$ &$param_name$, "
"$return_type$ *$return_name$)\n"
"$return_type$ *$return_name$, const QGrpcCallOptions &options)\n"
"{\n"
" return call<$param_type$>(\"$method_name$\"_L1, $param_name$, $return_name$);\n"
" return call<$param_type$>(\"$method_name$\"_L1, $param_name$, $return_name$, "
"options);\n"
"}\n";
}
const char *GrpcTemplates::ClientMethodDefinitionAsyncTemplate()
{
return "\nstd::shared_ptr<QGrpcCallReply> $classname$::$method_name$(const $param_type$ "
"&$param_name$)\n"
"&$param_name$, const QGrpcCallOptions &options)\n"
"{\n"
" return call<$param_type$>(\"$method_name$\"_L1, $param_name$);\n"
" return call<$param_type$>(\"$method_name$\"_L1, $param_name$, options);\n"
"}\n";
}
const char *GrpcTemplates::ClientMethodDefinitionAsync2Template()
{
return "\nvoid $classname$::$method_name$(const $param_type$ &$param_name$, const QObject "
"*context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback)\n"
"*context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const "
"QGrpcCallOptions &options)\n"
"{\n"
" std::shared_ptr<QGrpcCallReply> reply = call<$param_type$>(\"$method_name$\"_L1, "
"$param_name$);\n"
"$param_name$, options);\n"
" QObject::connect(reply.get(), &QGrpcCallReply::finished, context, [reply, "
"callback]() "
"{\n"
@ -165,7 +169,7 @@ const char *GrpcTemplates::ClientMethodDefinitionQml2Template()
const char *GrpcTemplates::ClientMethodServerStreamDeclarationTemplate()
{
return "std::shared_ptr<QGrpcStream> stream$method_name_upper$(const $param_type$ "
"&$param_name$);\n";
"&$param_name$, const QGrpcCallOptions &options = {});\n";
}
const char *GrpcTemplates::ClientMethodServerStream2DeclarationTemplate()
@ -185,9 +189,9 @@ const char *GrpcTemplates::ClientMethodServerStreamQmlDeclarationTemplate()
const char *GrpcTemplates::ClientMethodServerStreamDefinitionTemplate()
{
return "std::shared_ptr<QGrpcStream> $classname$::stream$method_name_upper$(const $param_type$ "
"&$param_name$)\n"
"&$param_name$, const QGrpcCallOptions &options)\n"
"{\n"
" return startStream<$param_type$>(\"$method_name$\"_L1, $param_name$);\n"
" return startStream<$param_type$>(\"$method_name$\"_L1, $param_name$, options);\n"
"}\n\n";
}

View File

@ -8,8 +8,6 @@
#endif
#include <QGrpcCredentials>
#include <QGrpcHttp2Channel>
#include <QGrpcInsecureCallCredentials>
#include <QGrpcInsecureChannelCredentials>
#include <QCoreApplication>
#include <QCryptographicHash>
@ -39,10 +37,8 @@ using namespace qtgrpc::tests;
static std::shared_ptr<TestService::Client> createHttp2Client()
{
auto client = std::make_shared<TestService::Client>();
auto channel = std::make_shared<QGrpcHttp2Channel>(QUrl("http://localhost:50051",
QUrl::StrictMode),
QGrpcInsecureChannelCredentials()
| QGrpcInsecureCallCredentials());
QGrpcChannelOptions channelOptions(QUrl("http://localhost:50051", QUrl::StrictMode));
auto channel = std::make_shared<QGrpcHttp2Channel>(channelOptions);
client->attachChannel(std::move(channel));
return client;
}
@ -52,7 +48,8 @@ static std::shared_ptr<TestService::Client> createHttp2Client()
static std::shared_ptr<TestService::Client> createGrpcSocketClient()
{
auto client = std::make_shared<TestService::Client>();
auto channel = std::make_shared<QGrpcChannel>(QString("unix:///tmp/test.sock"),
QGrpcChannelOptions channelOptions(QUrl("unix:///tmp/test.sock"));
auto channel = std::make_shared<QGrpcChannel>(channelOptions,
QGrpcChannel::InsecureChannelCredentials);
client->attachChannel(std::move(channel));
return client;
@ -61,7 +58,8 @@ static std::shared_ptr<TestService::Client> createGrpcSocketClient()
static std::shared_ptr<TestService::Client> createGrpcHttpClient()
{
auto client = std::make_shared<TestService::Client>();
auto channel = std::make_shared<QGrpcChannel>(QString("localhost:50051"),
QGrpcChannelOptions channelOptions(QUrl("localhost:50051"));
auto channel = std::make_shared<QGrpcChannel>(channelOptions,
QGrpcChannel::InsecureChannelCredentials);
client->attachChannel(std::move(channel));
return client;

View File

@ -9,9 +9,6 @@
# include <grpcpp/security/credentials.h>
#endif
#include <QGrpcHttp2Channel>
#include <QGrpcInsecureCallCredentials>
#include <QGrpcInsecureChannelCredentials>
#include <QGrpcSslCredentials>
#include <QCoreApplication>
#include <QCryptographicHash>
@ -94,9 +91,9 @@ void QtGrpcSslClientTest::Http2ChannelIncorrectSecureCredentialsTest()
// conf.setCaCertificates({QSslCertificate(cert)});
TestService::Client testClient;
testClient.attachChannel(std::make_shared<QGrpcHttp2Channel>(
QUrl("https://localhost:60051", QUrl::StrictMode),
QGrpcInsecureCallCredentials() | QGrpcSslCredentials(conf)));
QGrpcChannelOptions channelOptions(QUrl("https://localhost:60051", QUrl::StrictMode));
channelOptions.withSslConfiguration(conf);
testClient.attachChannel(std::make_shared<QGrpcHttp2Channel>(channelOptions));
SimpleStringMessage expected;
expected.setTestFieldString("Hello Qt!");
@ -113,9 +110,11 @@ void QtGrpcSslClientTest::GrpcHttpChannelIncorrectSecureCredentialsTest()
optionsList.append(QString::fromStdString(options.pem_root_certs));
optionsList.append(QString::fromStdString(options.pem_private_key));
optionsList.append(QString::fromStdString(options.pem_cert_chain));
testClient.attachChannel(std::make_shared<QGrpcChannel>(QUrl("localhost:60051"),
QGrpcChannel::SslDefaultCredentials,
optionsList));
QGrpcChannelOptions channelOptions(QUrl("localhost:60051"));
channelOptions.withCredentialList(optionsList);
testClient.attachChannel(std::make_shared<QGrpcChannel>(channelOptions,
QGrpcChannel::SslDefaultCredentials));
SimpleStringMessage expected;
expected.setTestFieldString("Hello Qt!");
@ -127,7 +126,8 @@ void QtGrpcSslClientTest::GrpcHttpChannelIncorrectSecureCredentialsTest()
void QtGrpcSslClientTest::GrpcSocketChannelIncorrectSecureCredentialsTest()
{
TestService::Client testClient;
testClient.attachChannel(std::make_shared<QGrpcChannel>(QUrl("unix:///tmp/test.sock"),
QGrpcChannelOptions channelOptions(QUrl("unix:///tmp/test.sock"));
testClient.attachChannel(std::make_shared<QGrpcChannel>(channelOptions,
QGrpcChannel::SslDefaultCredentials));
SimpleStringMessage expected;

View File

@ -3,8 +3,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QGrpcHttp2Channel>
#include <QGrpcInsecureCallCredentials>
#include <QGrpcInsecureChannelCredentials>
#include <QCoreApplication>
#include <QSignalSpy>
@ -33,8 +31,8 @@ void QtGrpcUnattachedChannelClientTest::CheckMethodsGeneration()
{
// Dummy compile time check of functions generation and interface compatibility
TestService::Client client;
client.attachChannel(std::make_shared<QGrpcHttp2Channel>(
QUrl(), QGrpcInsecureChannelCredentials() | QGrpcInsecureCallCredentials()));
QGrpcChannelOptions channelOptions{ QUrl() };
client.attachChannel(std::make_shared<QGrpcHttp2Channel>(channelOptions));
SimpleStringMessage request;
auto result = std::make_shared<SimpleStringMessage>();
client.testMethod(request, result.get());
@ -76,11 +74,10 @@ void QtGrpcUnattachedChannelClientTest::ClientSyncTestUnattachedChannelSignal()
void QtGrpcUnattachedChannelClientTest::AttachChannelThreadTest()
{
std::shared_ptr<QGrpcHttp2Channel> channel;
QGrpcChannelOptions channelOptions(QUrl("http://localhost:50051", QUrl::StrictMode));
std::shared_ptr<QThread> thread(QThread::create([&] {
const QUrl url("http://localhost:50051", QUrl::StrictMode);
channel = std::make_shared<QGrpcHttp2Channel>(url,
QGrpcInsecureCallCredentials()
| QGrpcInsecureChannelCredentials());
channel = std::make_shared<QGrpcHttp2Channel>(channelOptions);
}));
thread->start();
thread->wait();

View File

@ -11,50 +11,50 @@ Client::Client(QObject *parent)
{
}
QGrpcStatus Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret)
QGrpcStatus Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, ret);
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, ret, options);
}
std::shared_ptr<QGrpcCallReply> Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcCallReply> Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg);
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, options);
}
void Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback)
void Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg);
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, options);
QObject::connect(reply.get(), &QGrpcCallReply::finished, context, [reply, callback]() {
callback(reply);
});
}
std::shared_ptr<QGrpcStream> Client::streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcStream> Client::streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodServerStream"_L1, arg);
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodServerStream"_L1, arg, options);
}
QGrpcStatus Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret)
QGrpcStatus Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, ret);
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, ret, options);
}
std::shared_ptr<QGrpcCallReply> Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcCallReply> Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg);
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, options);
}
void Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback)
void Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg);
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, options);
QObject::connect(reply.get(), &QGrpcCallReply::finished, context, [reply, callback]() {
callback(reply);
});
}
std::shared_ptr<QGrpcStream> Client::streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcStream> Client::streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodBiStream"_L1, arg);
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodBiStream"_L1, arg, options);
}
} // namespace TestService

View File

@ -25,18 +25,18 @@ class Client : public QAbstractGrpcClient
public:
explicit Client(QObject *parent = nullptr);
QGrpcStatus testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret);
std::shared_ptr<QGrpcCallReply> testMethod(const qtgrpc::tests::SimpleStringMessage &arg);
Q_INVOKABLE void testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback);
QGrpcStatus testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcCallReply> testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
Q_INVOKABLE void testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg);
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QWeakPointer<qtgrpc::tests::SimpleStringMessage> &ret);
QGrpcStatus testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret);
std::shared_ptr<QGrpcCallReply> testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg);
Q_INVOKABLE void testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback);
QGrpcStatus testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcCallReply> testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
Q_INVOKABLE void testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg);
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QWeakPointer<qtgrpc::tests::SimpleStringMessage> &ret);

View File

@ -11,50 +11,50 @@ Client::Client(QObject *parent)
{
}
QGrpcStatus Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret)
QGrpcStatus Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, ret);
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, ret, options);
}
std::shared_ptr<QGrpcCallReply> Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcCallReply> Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg);
return call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, options);
}
void Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback)
void Client::testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg);
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethod"_L1, arg, options);
QObject::connect(reply.get(), &QGrpcCallReply::finished, context, [reply, callback]() {
callback(reply);
});
}
std::shared_ptr<QGrpcStream> Client::streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcStream> Client::streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodServerStream"_L1, arg);
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodServerStream"_L1, arg, options);
}
QGrpcStatus Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret)
QGrpcStatus Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, ret);
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, ret, options);
}
std::shared_ptr<QGrpcCallReply> Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcCallReply> Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg);
return call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, options);
}
void Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback)
void Client::testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options)
{
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg);
std::shared_ptr<QGrpcCallReply> reply = call<qtgrpc::tests::SimpleStringMessage>("testMethodClientStream"_L1, arg, options);
QObject::connect(reply.get(), &QGrpcCallReply::finished, context, [reply, callback]() {
callback(reply);
});
}
std::shared_ptr<QGrpcStream> Client::streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg)
std::shared_ptr<QGrpcStream> Client::streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options)
{
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodBiStream"_L1, arg);
return startStream<qtgrpc::tests::SimpleStringMessage>("testMethodBiStream"_L1, arg, options);
}
} // namespace TestService

View File

@ -25,18 +25,18 @@ class Client : public QAbstractGrpcClient
public:
explicit Client(QObject *parent = nullptr);
QGrpcStatus testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret);
std::shared_ptr<QGrpcCallReply> testMethod(const qtgrpc::tests::SimpleStringMessage &arg);
Q_INVOKABLE void testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback);
QGrpcStatus testMethod(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcCallReply> testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
Q_INVOKABLE void testMethod(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg);
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodServerStream(const qtgrpc::tests::SimpleStringMessage &arg, const QWeakPointer<qtgrpc::tests::SimpleStringMessage> &ret);
QGrpcStatus testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret);
std::shared_ptr<QGrpcCallReply> testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg);
Q_INVOKABLE void testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback);
QGrpcStatus testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, qtgrpc::tests::SimpleStringMessage *ret, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcCallReply> testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
Q_INVOKABLE void testMethodClientStream(const qtgrpc::tests::SimpleStringMessage &arg, const QObject *context, const std::function<void(std::shared_ptr<QGrpcCallReply>)> &callback, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg);
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QGrpcCallOptions &options = {});
std::shared_ptr<QGrpcStream> streamTestMethodBiStream(const qtgrpc::tests::SimpleStringMessage &arg, const QWeakPointer<qtgrpc::tests::SimpleStringMessage> &ret);