Skip to content

Commit 28f3bf0

Browse files
authored
fix ws empty frame (#218)
Signed-off-by: turuslan <[email protected]>
1 parent 3afa249 commit 28f3bf0

File tree

7 files changed

+117
-10
lines changed

7 files changed

+117
-10
lines changed

include/libp2p/basic/read.hpp

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef LIBP2P_BASIC_READ_HPP
7+
#define LIBP2P_BASIC_READ_HPP
8+
9+
#include <libp2p/basic/reader.hpp>
10+
#include <libp2p/common/span_size.hpp>
11+
#include <memory>
12+
13+
namespace libp2p {
14+
/// Read exactly `out.size()` bytes
15+
inline void read(const std::shared_ptr<basic::Reader> &reader,
16+
gsl::span<uint8_t> out,
17+
std::function<void(outcome::result<void>)> cb) {
18+
auto post_cb = [](decltype(reader) reader, decltype(cb) &&cb,
19+
outcome::result<size_t> r) {
20+
reader->deferReadCallback(r,
21+
[cb{std::move(cb)}](outcome::result<size_t> r) {
22+
if (r.has_error()) {
23+
cb(r.error());
24+
} else {
25+
cb(outcome::success());
26+
}
27+
});
28+
};
29+
if (out.empty()) {
30+
return post_cb(reader, std::move(cb), outcome::success());
31+
}
32+
// read some bytes
33+
reader->readSome(
34+
out, spanSize(out),
35+
[weak{std::weak_ptr{reader}}, out, cb{std::move(cb)},
36+
post_cb](outcome::result<size_t> n_res) mutable {
37+
auto reader = weak.lock();
38+
if (not reader) {
39+
return;
40+
}
41+
if (n_res.has_error()) {
42+
return post_cb(reader, std::move(cb), n_res.error());
43+
}
44+
auto n = n_res.value();
45+
if (n == 0) {
46+
throw std::logic_error{"libp2p::read zero bytes read"};
47+
}
48+
if (n > spanSize(out)) {
49+
throw std::logic_error{"libp2p::read too much bytes read"};
50+
}
51+
if (n == spanSize(out)) {
52+
// successfully read last bytes
53+
return post_cb(reader, std::move(cb), outcome::success());
54+
}
55+
// read remaining bytes
56+
read(reader, out.subspan(n), std::move(cb));
57+
});
58+
}
59+
} // namespace libp2p
60+
61+
#endif // LIBP2P_BASIC_READ_HPP
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef LIBP2P_BASIC_READ_RETURN_SIZE_HPP
7+
#define LIBP2P_BASIC_READ_RETURN_SIZE_HPP
8+
9+
#include <libp2p/basic/read.hpp>
10+
11+
namespace libp2p {
12+
/// Read exactly `out.size()` bytes
13+
inline void readReturnSize(const std::shared_ptr<basic::Reader> &reader,
14+
gsl::span<uint8_t> out,
15+
basic::Reader::ReadCallbackFunc cb) {
16+
read(reader, out,
17+
[n{spanSize(out)}, cb{std::move(cb)}](outcome::result<void> r) {
18+
if (r.has_error()) {
19+
cb(r.error());
20+
} else {
21+
cb(n);
22+
}
23+
});
24+
}
25+
} // namespace libp2p
26+
27+
#endif // LIBP2P_BASIC_READ_RETURN_SIZE_HPP

include/libp2p/layer/websocket/ssl_connection.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ namespace libp2p::layer {
1717
} // namespace libp2p::layer
1818

1919
namespace libp2p::connection {
20-
class SslConnection final : public LayerConnection {
20+
class SslConnection final
21+
: public LayerConnection,
22+
public std::enable_shared_from_this<SslConnection> {
2123
public:
2224
SslConnection(std::shared_ptr<boost::asio::io_context> io_context,
2325
std::shared_ptr<LayerConnection> connection,

src/layer/websocket/ssl_connection.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#include <libp2p/layer/websocket/ssl_connection.hpp>
77

8-
#include <boost/asio/read.hpp>
8+
#include <libp2p/basic/read_return_size.hpp>
99
#include <libp2p/common/ambigous_size.hpp>
1010
#include <libp2p/common/asio_buffer.hpp>
1111
#include <libp2p/common/asio_cb.hpp>
@@ -45,7 +45,7 @@ namespace libp2p::connection {
4545
void SslConnection::read(gsl::span<uint8_t> out, size_t bytes,
4646
libp2p::basic::Reader::ReadCallbackFunc cb) {
4747
ambigousSize(out, bytes);
48-
boost::asio::async_read(ssl_, asioBuffer(out), toAsioCbSize(std::move(cb)));
48+
readReturnSize(shared_from_this(), out, std::move(cb));
4949
}
5050

5151
void SslConnection::readSome(gsl::span<uint8_t> out, size_t bytes,

src/layer/websocket/ws_connection.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#include <libp2p/layer/websocket/ws_connection.hpp>
77

8-
#include <boost/asio/read.hpp>
8+
#include <libp2p/basic/read_return_size.hpp>
99
#include <libp2p/common/ambigous_size.hpp>
1010
#include <libp2p/common/asio_buffer.hpp>
1111
#include <libp2p/common/asio_cb.hpp>
@@ -129,14 +129,26 @@ namespace libp2p::connection {
129129
libp2p::basic::Reader::ReadCallbackFunc cb) {
130130
ambigousSize(out, bytes);
131131
SL_TRACE(log_, "read {} bytes", bytes);
132-
boost::asio::async_read(ws_, asioBuffer(out), toAsioCbSize(std::move(cb)));
132+
readReturnSize(shared_from_this(), out, std::move(cb));
133133
}
134134

135135
void WsConnection::readSome(gsl::span<uint8_t> out, size_t bytes,
136136
libp2p::basic::Reader::ReadCallbackFunc cb) {
137137
ambigousSize(out, bytes);
138138
SL_TRACE(log_, "read some upto {} bytes", bytes);
139-
ws_.async_read_some(asioBuffer(out), toAsioCbSize(std::move(cb)));
139+
auto on_read = [weak{weak_from_this()}, out, cb{std::move(cb)}](
140+
boost::system::error_code ec, size_t n) mutable {
141+
if (ec) {
142+
cb(ec);
143+
} else if (n != 0) {
144+
cb(n);
145+
} else if (auto self = weak.lock()) {
146+
self->readSome(out, spanSize(out), std::move(cb));
147+
} else {
148+
cb(boost::system::errc::broken_pipe);
149+
}
150+
};
151+
ws_.async_read_some(asioBuffer(out), std::move(on_read));
140152
}
141153

142154
void WsConnection::write(gsl::span<const uint8_t> in, //

src/security/tls/tls_connection.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include "tls_connection.hpp"
77
#include "tls_details.hpp"
88

9+
#include <libp2p/basic/read_return_size.hpp>
10+
#include <libp2p/common/ambigous_size.hpp>
11+
912
namespace libp2p::connection {
1013

1114
using TlsError = security::TlsError;
@@ -139,9 +142,9 @@ namespace libp2p::connection {
139142

140143
void TlsConnection::read(gsl::span<uint8_t> out, size_t bytes,
141144
Reader::ReadCallbackFunc f) {
145+
ambigousSize(out, bytes);
142146
SL_TRACE(log(), "reading {} bytes", bytes);
143-
boost::asio::async_read(socket_, makeBuffer(out, bytes),
144-
closeOnError(*this, std::move(f)));
147+
readReturnSize(shared_from_this(), out, std::move(f));
145148
}
146149

147150
void TlsConnection::readSome(gsl::span<uint8_t> out, size_t bytes,

src/transport/tcp/tcp_connection.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include <libp2p/transport/tcp/tcp_connection.hpp>
77

8+
#include <libp2p/basic/read_return_size.hpp>
9+
#include <libp2p/common/ambigous_size.hpp>
810
#include <libp2p/transport/tcp/tcp_util.hpp>
911

1012
#define TRACE_ENABLED 0
@@ -218,9 +220,9 @@ namespace libp2p::transport {
218220

219221
void TcpConnection::read(gsl::span<uint8_t> out, size_t bytes,
220222
TcpConnection::ReadCallbackFunc cb) {
223+
ambigousSize(out, bytes);
221224
TRACE("{} read {}", debug_str_, bytes);
222-
boost::asio::async_read(socket_, detail::makeBuffer(out, bytes),
223-
closeOnError(*this, std::move(cb)));
225+
readReturnSize(shared_from_this(), out, std::move(cb));
224226
}
225227

226228
void TcpConnection::readSome(gsl::span<uint8_t> out, size_t bytes,

0 commit comments

Comments
 (0)