forked from rsocket/rsocket-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFrameTransportImpl.cpp
More file actions
136 lines (111 loc) · 3.88 KB
/
FrameTransportImpl.cpp
File metadata and controls
136 lines (111 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) Facebook, Inc. and its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "rsocket/framing/FrameTransportImpl.h"
#include <folly/ExceptionWrapper.h>
#include <folly/io/IOBuf.h>
#include <glog/logging.h>
#include "rsocket/DuplexConnection.h"
#include "rsocket/framing/FrameProcessor.h"
namespace rsocket {
using namespace yarpl::flowable;
FrameTransportImpl::FrameTransportImpl(
std::unique_ptr<DuplexConnection> connection)
: connection_(std::move(connection)) {
CHECK(connection_);
}
FrameTransportImpl::~FrameTransportImpl() {
VLOG(1) << "~FrameTransport (" << this << ")";
}
void FrameTransportImpl::connect() {
CHECK(connection_);
// The onSubscribe call on the previous line may have called the terminating
// signal which would call disconnect/close.
if (connection_) {
// This may call ::onSubscribe in-line, which calls ::request on the
// provided subscription, which might deliver frames in-line. It can also
// call onComplete which will call disconnect/close and reset the
// connection_ while still inside of the connection_::setInput method. We
// will create a hard reference for that case and keep the object alive
// until setInput method returns
auto connectionCopy = connection_;
connectionCopy->setInput(shared_from_this());
}
}
void FrameTransportImpl::setFrameProcessor(
std::shared_ptr<FrameProcessor> frameProcessor) {
frameProcessor_ = std::move(frameProcessor);
if (frameProcessor_) {
CHECK(!isClosed());
connect();
}
}
void FrameTransportImpl::close() {
// Make sure we never try to call back into the processor.
frameProcessor_ = nullptr;
if (!connection_) {
return;
}
connection_.reset();
if (auto subscription = std::move(connectionInputSub_)) {
subscription->cancel();
}
}
void FrameTransportImpl::onSubscribe(
std::shared_ptr<Subscription> subscription) {
if (!connection_) {
return;
}
CHECK(!connectionInputSub_);
CHECK(frameProcessor_);
connectionInputSub_ = std::move(subscription);
connectionInputSub_->request(std::numeric_limits<int64_t>::max());
}
void FrameTransportImpl::onNext(std::unique_ptr<folly::IOBuf> frame) {
// Copy in case frame processing calls through to close().
if (auto const processor = frameProcessor_) {
processor->processFrame(std::move(frame));
}
}
void FrameTransportImpl::terminateProcessor(folly::exception_wrapper ex) {
// This method can be executed multiple times while terminating.
if (!frameProcessor_) {
// already terminated
return;
}
if (auto conn_sub = std::move(connectionInputSub_)) {
conn_sub->cancel();
}
auto frameProcessor = std::move(frameProcessor_);
VLOG(3) << this << " terminating frame processor ex=" << ex.what();
frameProcessor->onTerminal(std::move(ex));
}
void FrameTransportImpl::onComplete() {
VLOG(3) << "FrameTransport received onComplete";
terminateProcessor(folly::exception_wrapper());
}
void FrameTransportImpl::onError(folly::exception_wrapper ex) {
VLOG(3) << "FrameTransport received onError: " << ex.what();
terminateProcessor(std::move(ex));
}
void FrameTransportImpl::outputFrameOrDrop(
std::unique_ptr<folly::IOBuf> frame) {
if (connection_) {
connection_->send(std::move(frame));
}
}
bool FrameTransportImpl::isConnectionFramed() const {
CHECK(connection_);
return connection_->isFramed();
}
} // namespace rsocket