mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 07:36:10 -04:00
added l2cap refactored flow to socket
This commit is contained in:
@@ -14,28 +14,104 @@
|
||||
|
||||
#include "internal/platform/implementation/linux/ble_l2cap_socket.h"
|
||||
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/crypto.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "proto/mediums/ble_frames.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
|
||||
// Migrated from bespoke l2cap socket stream semantics to linux platform stream
|
||||
// semantics
|
||||
//
|
||||
namespace {
|
||||
|
||||
constexpr int kFrameHeaderSize = 4;
|
||||
constexpr int kMaxFrameSize = 1024 * 1024;
|
||||
|
||||
std::string EncodeFrameLength(uint32_t length) {
|
||||
return std::string{
|
||||
static_cast<char>((length >> 24) & 0xFF),
|
||||
static_cast<char>((length >> 16) & 0xFF),
|
||||
static_cast<char>((length >> 8) & 0xFF),
|
||||
static_cast<char>(length & 0xFF),
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t DecodeFrameLength(absl::string_view header) {
|
||||
return (static_cast<uint32_t>(static_cast<unsigned char>(header[0])) << 24) |
|
||||
(static_cast<uint32_t>(static_cast<unsigned char>(header[1])) << 16) |
|
||||
(static_cast<uint32_t>(static_cast<unsigned char>(header[2])) << 8) |
|
||||
static_cast<uint32_t>(static_cast<unsigned char>(header[3]));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Exception BleL2capOutputStream::Write(absl::string_view data) {
|
||||
if (data.size() > std::numeric_limits<uint32_t>::max()) {
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
std::string frame = EncodeFrameLength(static_cast<uint32_t>(data.size()));
|
||||
frame.append(data.data(), data.size());
|
||||
return stream_.Write(frame);
|
||||
}
|
||||
|
||||
Exception BleL2capOutputStream::Flush() {
|
||||
return stream_.Flush();
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BleL2capInputStream::Read(std::int64_t size) {
|
||||
if (size <= 0) {
|
||||
return ExceptionOr<ByteArray>(ByteArray(std::string()));
|
||||
}
|
||||
LOG(INFO) << __func__ << ": trying to read " << size << " payload bytes";
|
||||
|
||||
while (pending_.empty()) {
|
||||
ExceptionOr<ByteArray> packet = stream_.Read(kMaxFrameSize);
|
||||
if (!packet.ok()) {
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
std::string packet_data = packet.result().string_data();
|
||||
|
||||
if (packet_data.empty()) {
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
wire_buffer_.append(packet_data);
|
||||
|
||||
while (wire_buffer_.size() >= kFrameHeaderSize) {
|
||||
uint32_t frame_length = DecodeFrameLength(absl::string_view(
|
||||
wire_buffer_.data(), kFrameHeaderSize));
|
||||
if (frame_length > kMaxFrameSize) {
|
||||
LOG(ERROR) << __func__ << ": invalid L2CAP frame length "
|
||||
<< frame_length;
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
size_t full_frame_size = kFrameHeaderSize + frame_length;
|
||||
if (wire_buffer_.size() < full_frame_size) {
|
||||
break;
|
||||
}
|
||||
|
||||
pending_.append(wire_buffer_.data() + kFrameHeaderSize, frame_length);
|
||||
wire_buffer_.erase(0, full_frame_size);
|
||||
|
||||
if (!pending_.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
size_t bytes_to_return = std::min(static_cast<size_t>(size), pending_.size());
|
||||
std::string out = pending_.substr(0, bytes_to_return);
|
||||
pending_.erase(0, bytes_to_return);
|
||||
return ExceptionOr<ByteArray>(ByteArray(std::move(out)));
|
||||
}
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
Reference in New Issue
Block a user