1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtGrpc/qgrpccalloptions.h>
5#include <QtGrpc/qgrpcoperationcontext.h>
6#include <QtGrpc/qgrpcstatus.h>
7
8#include <QtProtobuf/qprotobufserializer.h>
9
10#include <QtCore/private/qobject_p.h>
11#include <QtCore/qbytearray.h>
12#include <QtCore/qbytearrayview.h>
13#include <QtCore/qlatin1stringview.h>
14
15#include <utility>
16
17QT_BEGIN_NAMESPACE
18
19/*!
20 \class QGrpcOperationContext
21 \inmodule QtGrpc
22 \since 6.7
23 \brief The QGrpcOperationContext class provides context for communication
24 between an individual \gRPC operation and a channel.
25
26 QGrpcOperationContext is constructed internally when a remote procedure call
27 (RPC) is requested, mediating interaction between the client's operation
28 request and the channel's operation outcome.
29
30 RPCs requested on the client interface return specializations of
31 QGrpcOperation, such as QGrpcCallReply, QGrpcServerStream,
32 QGrpcClientStream, or QGrpcBidiStream. These classes are implicitly
33 integrated with the underlying QGrpcOperationContext counterpart.
34
35 \note Don't use this class directly unless implementing a custom channel.
36
37 The signals contained within this class are used to build the communication
38 between the client-facing QGrpcOperation and the QAbstractGrpcChannel
39 implementation. These operations are asynchronous in nature, and multiple
40 RPCs can operate on the same channel concurrently. Channels typically treat
41 all operations the same, and it is the channel's responsibility to
42 correctly support and restrict the subset of features its RPC type
43 supports.
44
45 Signals which should only be emitted by the channel's implementation are:
46 \list
47 \li finished()
48 \li messageReceived()
49 \endlist
50
51 Signals which will be emitted by QGrpcOperation and its specializations are:
52 \list
53 \li cancelRequested()
54 \li writeMessageRequested()
55 \li writesDoneRequested()
56 \endlist
57
58 Custom implementations of QAbstractGrpcChannel must handle the client's
59 signals, as no default signal handling is provided, and emit their own
60 signals accordingly.
61*/
62
63/*!
64 \fn void finished(const QGrpcStatus &status)
65
66 This signal should be emitted by the channel when an RPC finishes.
67
68 It usually means that the server sent a \a status for the requested RPC and
69 closed the connection. Implementations of QAbstractGrpcChannel should
70 detect this situation and emit the signal.
71
72 After receiving this signal, no further communication should occur through
73 this operation context. The client side may then safely delete the
74 corresponding RPC object.
75
76 \note This signal is implicitly connected to the QGrpcOperation counterpart.
77
78 \sa QGrpcOperation::finished
79*/
80
81/*!
82 \fn void QGrpcOperationContext::messageReceived(const QByteArray &data)
83
84 This signal should be emitted by the channel when a new chunk of \a data is
85 received from the server.
86
87 For client streams and unary calls, this means that the single and final
88 response has arrived and communication is about to finish.
89
90 For server and bidirectional streams, this signal should be continuously
91 emitted by the channel upon receiving each new messages.
92
93 \note This signal is implicitly connected to the QGrpcOperation
94 counterpart.
95
96 \sa QGrpcServerStream::messageReceived
97 \sa QGrpcBidiStream::messageReceived
98*/
99
100/*!
101 \fn void QGrpcOperationContext::cancelRequested()
102
103 This signal is emitted by QGrpcOperation when requesting cancellation of the
104 communication.
105
106 The channel is expected to connect its cancellation logic to this signal and
107 attempt to cancel the RPC and return immediately. Successful cancellation
108 cannot be guaranteed. Further processing of the data received from a
109 channel is not required and should be avoided.
110
111 \sa QGrpcOperation::cancel
112*/
113
114/*!
115 \fn void QGrpcOperationContext::writeMessageRequested(const QByteArray &data)
116
117 This signal is emitted by QGrpcClientStream or QGrpcBidiStream when it has
118 serialized \a data ready for a channel to deliver.
119
120 The channel is expected to connect its writing logic to this signal and wrap
121 the serialized data in channel-related headers before writing it to the
122 wire.
123
124 \sa QGrpcClientStream::writeMessage
125 \sa QGrpcBidiStream::writeMessage
126*/
127
128/*!
129 \fn void QGrpcOperationContext::writesDoneRequested()
130
131 This signal is emitted by QGrpcClientStream or QGrpcBidiStream to indicate
132 that it's done writing messages. The channel should respond to this by
133 half-closing the stream.
134
135 \note After receiving this signal no more write operations are permitted
136 for the streaming RPCs. The server can still send messages, which should be
137 forwarded with messageReceived().
138
139 \sa QGrpcClientStream::writesDone
140 \sa QGrpcBidiStream::writesDone
141*/
142
143class QGrpcOperationContextPrivate : public QObjectPrivate
144{
145 Q_DECLARE_PUBLIC(QGrpcOperationContext)
146public:
147 QGrpcOperationContextPrivate(QLatin1StringView method_, QLatin1StringView service_,
148 QByteArrayView argument_, QGrpcCallOptions options_,
149 std::shared_ptr<QAbstractProtobufSerializer> &&serializer_)
150 : method(method_), service(service_), argument(argument_.toByteArray()),
151 options(std::move(options_)), serializer(std::move(serializer_))
152 {
153 }
154
155 QLatin1StringView method;
156 QLatin1StringView service;
157 QByteArray argument;
158 QGrpcCallOptions options;
159 std::shared_ptr<QAbstractProtobufSerializer> serializer;
160 QHash<QByteArray, QByteArray> serverMetadata;
161};
162
163/*!
164 \internal
165
166 Constructs an operation context with \a method and \a service name. The
167 initial serialized message \a arg is used to start a call with the \a
168 options and the selected \a serializer used for the RPC.
169
170 \note This class can only be constructed by QAbstractGrpcChannel.
171*/
172QGrpcOperationContext::QGrpcOperationContext(QLatin1StringView method, QLatin1StringView service,
173 QByteArrayView arg, const QGrpcCallOptions &options,
174 std::shared_ptr<QAbstractProtobufSerializer>
175 serializer,
176 PrivateConstructor /*unused*/)
177 : QObject(*new QGrpcOperationContextPrivate(method, service, arg, options,
178 std::move(serializer)))
179{
180}
181
182/*!
183 Destroys the operation-context.
184*/
185QGrpcOperationContext::~QGrpcOperationContext() = default;
186
187/*!
188 Returns the method name of the service associated with this
189 operation-context.
190*/
191QLatin1StringView QGrpcOperationContext::method() const noexcept
192{
193 Q_D(const QGrpcOperationContext);
194 return d->method;
195}
196
197/*!
198 Returns the service name associated with this operation-context.
199*/
200QLatin1StringView QGrpcOperationContext::service() const noexcept
201{
202 Q_D(const QGrpcOperationContext);
203 return d->service;
204}
205
206/*!
207 Returns the serialized argument that is utilized by this operation-context.
208*/
209QByteArrayView QGrpcOperationContext::argument() const noexcept
210{
211 Q_D(const QGrpcOperationContext);
212 return d->argument;
213}
214
215/*!
216 Returns the call options that is utilized by this operation-context.
217
218 For channel-wide options, see QGrpcChannelOptions.
219*/
220const QGrpcCallOptions &QGrpcOperationContext::callOptions() const & noexcept
221{
222 Q_D(const QGrpcOperationContext);
223 return d->options;
224}
225
226/*!
227 Returns the serializer of this operation-context
228*/
229std::shared_ptr<const QAbstractProtobufSerializer>
230QGrpcOperationContext::serializer() const
231{
232 Q_D(const QGrpcOperationContext);
233 return d->serializer;
234}
235
236/*!
237 Returns the metadata received from the server.
238
239 \note This method is used implicitly by the QGrpcOperation counterpart.
240*/
241const QHash<QByteArray, QByteArray> &QGrpcOperationContext::serverMetadata() const & noexcept
242{
243 Q_D(const QGrpcOperationContext);
244 return d->serverMetadata;
245}
246
247/*!
248 \fn void QGrpcOperationContext::setServerMetadata(const QHash<QByteArray, QByteArray> &metadata)
249 \fn void QGrpcOperationContext::setServerMetadata(QHash<QByteArray, QByteArray> &&metadata)
250
251 Sets the server \a metadata received from the service.
252*/
253void QGrpcOperationContext::setServerMetadata(const QHash<QByteArray, QByteArray> &metadata)
254{
255 Q_D(QGrpcOperationContext);
256 d->serverMetadata = metadata;
257}
258
259void QGrpcOperationContext::setServerMetadata(QHash<QByteArray, QByteArray> &&metadata)
260{
261 Q_D(QGrpcOperationContext);
262 d->serverMetadata = std::move(metadata);
263}
264
265// For future extensions
266bool QGrpcOperationContext::event(QEvent *event)
267{
268 return QObject::event(event);
269}
270
271QT_END_NAMESPACE
272
273#include "moc_qgrpcoperationcontext.cpp"
274

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtgrpc/src/grpc/qgrpcoperationcontext.cpp