1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#include <QtGrpc/private/qabstractgrpcchannel_p.h>
6#include <QtGrpc/qabstractgrpcchannel.h>
7#include <QtGrpc/qgrpccalloptions.h>
8#include <QtGrpc/qgrpccallreply.h>
9#include <QtGrpc/qgrpcoperationcontext.h>
10#include <QtGrpc/qgrpcstream.h>
11
12#include <QtCore/qbytearrayview.h>
13#include <QtCore/qlatin1stringview.h>
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \class QAbstractGrpcChannel
19 \inmodule QtGrpc
20 \brief The QAbstractGrpcChannel class provides an interface for
21 implementing the transport layer of \gRPC operations.
22
23 Implement this interface to create a custom channel for \gRPC
24 transportation. The QGrpcHttp2Channel class is provided as a fully featured
25 implementation of QAbstractGrpcChannel for HTTP/2 communication.
26
27 \sa QGrpcChannelOptions, QGrpcHttp2Channel
28*/
29
30/*!
31 \fn virtual std::shared_ptr<QAbstractProtobufSerializer> QAbstractGrpcChannel::serializer() const = 0
32
33 This pure virtual function retrieves the QAbstractProtobufSerializer used
34 for the serialization and deserialization of messages.
35*/
36
37/*!
38 \fn virtual void QAbstractGrpcChannel::call(std::shared_ptr<QGrpcOperationContext> operationContext) = 0
39 \since 6.7
40
41//! [abstract-rpc-desc]
42 This pure virtual function is called when a user starts a new RPC through
43 the generated client interface. The \a operationContext should be used to
44 communicate with the corresponding RPC handler, which is a derived type of
45 the QGrpcOperation object.
46
47 This function should start the corresponding RPC on the channel side. The
48 implementation must be asynchronous and must not block the calling thread.
49
50 \note It is the channel's responsibility to support and restrict the subset
51 of features that its RPC type allows.
52//! [abstract-rpc-desc]
53*/
54
55/*!
56 \fn virtual void QAbstractGrpcChannel::serverStream(std::shared_ptr<QGrpcOperationContext> operationContext) = 0
57 \since 6.7
58
59 \include qabstractgrpcchannel.cpp abstract-rpc-desc
60*/
61
62/*!
63 \fn virtual void QAbstractGrpcChannel::clientStream(std::shared_ptr<QGrpcOperationContext> operationContext) = 0
64 \since 6.7
65
66 \include qabstractgrpcchannel.cpp abstract-rpc-desc
67*/
68
69/*!
70 \fn virtual void QAbstractGrpcChannel::bidiStream(std::shared_ptr<QGrpcOperationContext> operationContext) = 0
71 \since 6.7
72
73 \include qabstractgrpcchannel.cpp abstract-rpc-desc
74*/
75
76/*!
77 Default-constructs the QAbstractGrpcChannel.
78*/
79QAbstractGrpcChannel::QAbstractGrpcChannel()
80 : d_ptr(std::make_unique<QAbstractGrpcChannelPrivate>(args: QGrpcChannelOptions{}))
81{
82}
83
84/*!
85 \since 6.8
86 \internal
87
88 Constructs the QAbstractGrpcChannel using the Private implementation to
89 reuse the d_ptr.
90*/
91QAbstractGrpcChannel::QAbstractGrpcChannel(QAbstractGrpcChannelPrivate &dd) : d_ptr(&dd)
92{
93}
94
95/*!
96 Constructs the QAbstractGrpcChannel using the specified \a options.
97*/
98QAbstractGrpcChannel::QAbstractGrpcChannel(const QGrpcChannelOptions &options)
99 : d_ptr(std::make_unique<QAbstractGrpcChannelPrivate>(args: options))
100{
101}
102
103/*!
104 Destroys the QAbstractGrpcChannel.
105*/
106QAbstractGrpcChannel::~QAbstractGrpcChannel() = default;
107
108/*!
109 Returns the options utilized by the channel.
110
111 \sa setChannelOptions
112*/
113const QGrpcChannelOptions &QAbstractGrpcChannel::channelOptions() const & noexcept
114{
115 Q_D(const QAbstractGrpcChannel);
116 return d->channelOptions;
117}
118
119/*!
120 \fn void QAbstractGrpcChannel::setChannelOptions(const QGrpcChannelOptions &options) noexcept
121 \fn void QAbstractGrpcChannel::setChannelOptions(QGrpcChannelOptions &&options) noexcept
122 \since 6.8
123
124 Sets the channel \a options.
125
126 \note The updated channel options do not affect currently active calls or streams.
127 The revised options will apply only to new RPCs made through this channel.
128
129 \sa channelOptions
130*/
131void QAbstractGrpcChannel::setChannelOptions(const QGrpcChannelOptions &options)
132{
133 Q_D(QAbstractGrpcChannel);
134 d->channelOptions = options;
135}
136
137void QAbstractGrpcChannel::setChannelOptions(QGrpcChannelOptions &&options)
138{
139 Q_D(QAbstractGrpcChannel);
140 d->channelOptions = std::move(options);
141}
142
143/*!
144 \internal
145
146//! [private-rpc-desc]
147 This function is called when a user initiates a new RPC through the
148 generated client interface via QGrpcClientBase. It creates the
149 QGrpcOperationContext and the corresponding RPC handler, establishing the
150 required connections between the two.
151//! [private-rpc-desc]
152*/
153std::unique_ptr<QGrpcCallReply> QAbstractGrpcChannel::call(QLatin1StringView method,
154 QLatin1StringView service,
155 QByteArrayView arg,
156 const QGrpcCallOptions &options)
157{
158 auto operationContext = std::make_shared<
159 QGrpcOperationContext>(args&: method, args&: service, args&: arg, args: options, args: serializer(),
160 args: QGrpcOperationContext::PrivateConstructor());
161
162 QObject::connect(sender: operationContext.get(), signal: &QGrpcOperationContext::writeMessageRequested,
163 context: operationContext.get(), slot: []() {
164 Q_ASSERT_X(false, "QAbstractGrpcChannel::call",
165 "QAbstractGrpcChannel::call disallows the "
166 "'writeMessageRequested' signal from "
167 "QGrpcOperationContext");
168 });
169
170 auto reply = std::make_unique<QGrpcCallReply>(args&: operationContext);
171 call(operationContext);
172
173 return reply;
174}
175
176/*!
177 \internal
178 \include qabstractgrpcchannel.cpp private-rpc-desc
179*/
180std::unique_ptr<QGrpcServerStream>
181QAbstractGrpcChannel::serverStream(QLatin1StringView method, QLatin1StringView service,
182 QByteArrayView arg, const QGrpcCallOptions &options)
183{
184 auto operationContext = std::make_shared<
185 QGrpcOperationContext>(args&: method, args&: service, args&: arg, args: options, args: serializer(),
186 args: QGrpcOperationContext::PrivateConstructor());
187
188 QObject::connect(sender: operationContext.get(), signal: &QGrpcOperationContext::writeMessageRequested,
189 context: operationContext.get(), slot: []() {
190 Q_ASSERT_X(false, "QAbstractGrpcChannel::serverStream",
191 "QAbstractGrpcChannel::serverStream disallows "
192 "the 'writeMessageRequested' signal from "
193 "QGrpcOperationContext");
194 });
195
196 auto stream = std::make_unique<QGrpcServerStream>(args&: operationContext);
197 serverStream(operationContext);
198
199 return stream;
200}
201
202/*!
203 \internal
204 \include qabstractgrpcchannel.cpp private-rpc-desc
205*/
206std::unique_ptr<QGrpcClientStream>
207QAbstractGrpcChannel::clientStream(QLatin1StringView method, QLatin1StringView service,
208 QByteArrayView arg, const QGrpcCallOptions &options)
209{
210 auto operationContext = std::make_shared<
211 QGrpcOperationContext>(args&: method, args&: service, args&: arg, args: options, args: serializer(),
212 args: QGrpcOperationContext::PrivateConstructor());
213
214 auto stream = std::make_unique<QGrpcClientStream>(args&: operationContext);
215 clientStream(operationContext);
216
217 return stream;
218}
219
220/*!
221 \internal
222 \include qabstractgrpcchannel.cpp private-rpc-desc
223*/
224std::unique_ptr<QGrpcBidiStream> QAbstractGrpcChannel::bidiStream(QLatin1StringView method,
225 QLatin1StringView service,
226 QByteArrayView arg,
227 const QGrpcCallOptions &options)
228{
229 auto operationContext = std::make_shared<
230 QGrpcOperationContext>(args&: method, args&: service, args&: arg, args: options, args: serializer(),
231 args: QGrpcOperationContext::PrivateConstructor());
232
233 auto stream = std::make_unique<QGrpcBidiStream>(args&: operationContext);
234 bidiStream(operationContext);
235
236 return stream;
237}
238
239QT_END_NAMESPACE
240

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