Skip to content

Commit 69e113c

Browse files
authored
Add support for RequestResponse (#117)
* Add support for RequestResponse * rebase * Removed all questions from the code since they are mostly for my understanding, and the code should work properly due to copy-paste reasons Check the request payload is not sent twice RequestResponseRequesterBase * Publisher responds with one single RESPONSE frame that has the COMPLETE flag set
2 parents ec5e7fb + e11463b commit 69e113c

23 files changed

Lines changed: 588 additions & 7 deletions

‎CMakeLists.txt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ add_library(
8282
src/automata/ChannelRequester.h
8383
src/automata/ChannelResponder.cpp
8484
src/automata/ChannelResponder.h
85+
src/automata/RequestResponseRequester.cpp
86+
src/automata/RequestResponseRequester.h
87+
src/automata/RequestResponseResponder.cpp
88+
src/automata/RequestResponseResponder.h
8589
src/automata/StreamSubscriptionRequesterBase.cpp
8690
src/automata/StreamSubscriptionRequesterBase.h
8791
src/automata/StreamSubscriptionResponderBase.cpp

‎TARGETS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ cxx_library(
3838
'src/AbstractStreamAutomaton.cpp',
3939
'src/automata/ChannelRequester.cpp',
4040
'src/automata/ChannelResponder.cpp',
41+
'src/automata/RequestResponseRequester.cpp',
42+
'src/automata/RequestResponseResponder.cpp',
4143
'src/automata/StreamSubscriptionRequesterBase.cpp',
4244
'src/automata/StreamSubscriptionResponderBase.cpp',
4345
'src/automata/StreamRequester.cpp',

‎src/AbstractStreamAutomaton.cpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ void AbstractStreamAutomaton::onNextFrame(
4747
case FrameType::REQUEST_N:
4848
deserializeAndDispatch<Frame_REQUEST_N>(std::move(payload));
4949
return;
50+
case FrameType::REQUEST_RESPONSE:
51+
deserializeAndDispatch<Frame_REQUEST_RESPONSE>(std::move(payload));
52+
return;
5053
case FrameType::CANCEL:
5154
deserializeAndDispatch<Frame_CANCEL>(std::move(payload));
5255
return;

‎src/AbstractStreamAutomaton.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ConnectionAutomaton;
1717
class Frame_REQUEST_STREAM;
1818
class Frame_REQUEST_SUB;
1919
class Frame_REQUEST_CHANNEL;
20+
class Frame_REQUEST_RESPONSE;
2021
class Frame_REQUEST_N;
2122
class Frame_CANCEL;
2223
class Frame_RESPONSE;
@@ -96,6 +97,7 @@ class AbstractStreamAutomaton {
9697
virtual void onNextFrame(Frame_REQUEST_SUB&& frame) = 0;
9798
virtual void onNextFrame(Frame_REQUEST_CHANNEL&& frame) = 0;
9899
virtual void onNextFrame(Frame_REQUEST_N&& frame) = 0;
100+
virtual void onNextFrame(Frame_REQUEST_RESPONSE&& frame) = 0;
99101
virtual void onNextFrame(Frame_CANCEL&& frame) = 0;
100102
virtual void onNextFrame(Frame_RESPONSE&& frame) = 0;
101103
virtual void onNextFrame(Frame_ERROR&& frame) = 0;

‎src/Frame.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ std::ostream& operator<<(std::ostream& os, FrameType type) {
4747
return os << "REQUEST_CHANNEL";
4848
case FrameType::REQUEST_N:
4949
return os << "REQUEST_N";
50+
case FrameType::REQUEST_RESPONSE:
51+
return os << "REQUEST_RESPONSE";
5052
case FrameType::REQUEST_FNF:
5153
return os << "REQUEST_FNF";
5254
case FrameType::CANCEL:
@@ -192,6 +194,34 @@ std::ostream& operator<<(std::ostream& os, const Frame_REQUEST_N& frame) {
192194
}
193195
/// @}
194196

197+
/// @{
198+
std::unique_ptr<folly::IOBuf> Frame_REQUEST_RESPONSE::serializeOut() {
199+
auto queue = createBufferQueue(FrameHeader::kSize + payload_.framingSize());
200+
folly::io::QueueAppender appender(&queue, /* do not grow */ 0);
201+
202+
header_.serializeInto(appender);
203+
payload_.serializeInto(appender);
204+
return queue.move();
205+
}
206+
207+
bool Frame_REQUEST_RESPONSE::deserializeFrom(std::unique_ptr<folly::IOBuf> in) {
208+
folly::io::Cursor cur(in.get());
209+
try {
210+
header_.deserializeFrom(cur);
211+
payload_.deserializeFrom(cur, header_.flags_);
212+
} catch (...) {
213+
return false;
214+
}
215+
return true;
216+
}
217+
218+
std::ostream& operator<<(
219+
std::ostream& os,
220+
const Frame_REQUEST_RESPONSE& frame) {
221+
return os << frame.header_ << ", " << frame.payload_;
222+
}
223+
/// @}
224+
195225
/// @{
196226
std::unique_ptr<folly::IOBuf> Frame_REQUEST_FNF::serializeOut() {
197227
auto queue = createBufferQueue(FrameHeader::kSize + payload_.framingSize());

‎src/Frame.h‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ enum class FrameType : uint16_t {
3838
SETUP = 0x0001,
3939
LEASE = 0x0002,
4040
KEEPALIVE = 0x0003,
41-
// REQUEST_RESPONSE = 0x0004,
41+
REQUEST_RESPONSE = 0x0004,
4242
REQUEST_FNF = 0x0005,
4343
REQUEST_STREAM = 0x0006,
4444
REQUEST_SUB = 0x0007,
@@ -218,6 +218,29 @@ class Frame_REQUEST_CHANNEL : public Frame_REQUEST_Base {
218218
: Frame_REQUEST_CHANNEL(streamId, flags, 0, std::move(payload)) {}
219219
};
220220

221+
class Frame_REQUEST_RESPONSE {
222+
public:
223+
static constexpr bool Trait_CarriesAllowance = false;
224+
225+
Frame_REQUEST_RESPONSE() = default;
226+
Frame_REQUEST_RESPONSE(StreamId streamId, FrameFlags flags, Payload payload)
227+
: header_(
228+
FrameType::REQUEST_RESPONSE,
229+
flags | payload.getFlags(),
230+
streamId),
231+
payload_(std::move(payload)) {
232+
payload_.checkFlags(header_.flags_); // to verify the client didn't set
233+
// METADATA and provided none
234+
}
235+
236+
std::unique_ptr<folly::IOBuf> serializeOut();
237+
bool deserializeFrom(std::unique_ptr<folly::IOBuf> in);
238+
239+
FrameHeader header_;
240+
Payload payload_;
241+
};
242+
std::ostream& operator<<(std::ostream&, const Frame_REQUEST_RESPONSE&);
243+
221244
class Frame_REQUEST_FNF {
222245
public:
223246
static constexpr bool Trait_CarriesAllowance = false;

‎src/NullRequestHandler.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ void NullRequestHandler::handleRequestSubscription(
4646
response.onError(std::runtime_error("NullRequestHandler"));
4747
}
4848

49+
void NullRequestHandler::handleRequestResponse(
50+
Payload /*request*/,
51+
Subscriber<Payload>& response) {
52+
response.onSubscribe(createManagedInstance<NullSubscription>());
53+
response.onError(std::runtime_error("NullRequestHandler"));
54+
}
55+
4956
void NullRequestHandler::handleFireAndForgetRequest(Payload /*request*/) {}
5057

5158
void NullRequestHandler::handleMetadataPush(

‎src/NullRequestHandler.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class NullRequestHandler : public RequestHandler {
3535
void handleRequestSubscription(Payload request, Subscriber<Payload>& response)
3636
override;
3737

38+
void handleRequestResponse(Payload request, Subscriber<Payload>& response)
39+
override;
40+
3841
void handleFireAndForgetRequest(Payload request) override;
3942

4043
void handleMetadataPush(std::unique_ptr<folly::IOBuf> request) override;

‎src/ReactiveSocket.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "src/RequestHandler.h"
1919
#include "src/automata/ChannelRequester.h"
2020
#include "src/automata/ChannelResponder.h"
21+
#include "src/automata/RequestResponseRequester.h"
22+
#include "src/automata/RequestResponseResponder.h"
2123
#include "src/automata/StreamRequester.h"
2224
#include "src/automata/StreamResponder.h"
2325
#include "src/automata/SubscriptionRequester.h"
@@ -166,6 +168,21 @@ void ReactiveSocket::requestFireAndForget(Payload request) {
166168
connection_->outputFrameOrEnqueue(frame.serializeOut());
167169
}
168170

171+
void ReactiveSocket::requestResponse(
172+
Payload payload,
173+
Subscriber<Payload>& responseSink) {
174+
// TODO(stupaq): handle any exceptions
175+
StreamId streamId = nextStreamId_;
176+
nextStreamId_ += 2;
177+
RequestResponseRequester::Parameters params = {connection_, streamId};
178+
auto automaton = new RequestResponseRequester(params);
179+
connection_->addStream(streamId, *automaton);
180+
automaton->subscribe(responseSink);
181+
responseSink.onSubscribe(*automaton);
182+
automaton->onNext(std::move(payload));
183+
automaton->start();
184+
}
185+
169186
void ReactiveSocket::metadataPush(std::unique_ptr<folly::IOBuf> metadata) {
170187
connection_->outputFrameOrEnqueue(
171188
Frame_METADATA_PUSH(std::move(metadata)).serializeOut());
@@ -247,6 +264,19 @@ bool ReactiveSocket::createResponder(
247264
automaton->start();
248265
break;
249266
}
267+
case FrameType::REQUEST_RESPONSE: {
268+
Frame_REQUEST_RESPONSE frame;
269+
if (!frame.deserializeFrom(std::move(serializedFrame))) {
270+
return false;
271+
}
272+
SubscriptionResponder::Parameters params = {connection_, streamId};
273+
auto automaton = new RequestResponseResponder(params);
274+
connection_->addStream(streamId, *automaton);
275+
handler_->handleRequestResponse(std::move(frame.payload_), *automaton);
276+
automaton->onNextFrame(std::move(frame));
277+
automaton->start();
278+
break;
279+
}
250280
case FrameType::REQUEST_FNF: {
251281
Frame_REQUEST_FNF frame;
252282
if (!frame.deserializeFrom(std::move(serializedFrame))) {

‎src/ReactiveSocket.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class ReactiveSocket {
7878

7979
void requestFireAndForget(Payload request);
8080

81+
void requestResponse(Payload payload, Subscriber<Payload>& responseSink);
82+
8183
void close();
8284

8385
void onClose(CloseListener listener);

0 commit comments

Comments
 (0)