1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "link_layer_socket_device.h"
18
19 #include <type_traits> // for remove_extent_t
20
21 #include "log.h" // for ASSERT, LOG_INFO, LOG_ERROR, LOG_WARN
22 #include "packet/bit_inserter.h" // for BitInserter
23 #include "packet/iterator.h" // for Iterator
24 #include "packet/packet_view.h" // for PacketView, kLittleEndian
25 #include "packet/raw_builder.h" // for RawBuilder
26 #include "packet/view.h" // for View
27 #include "phy.h" // for Phy, Phy::Type
28
29 using std::vector;
30
31 namespace rootcanal {
32
LinkLayerSocketDevice(std::shared_ptr<AsyncDataChannel> socket_fd,Phy::Type phy_type)33 LinkLayerSocketDevice::LinkLayerSocketDevice(
34 std::shared_ptr<AsyncDataChannel> socket_fd, Phy::Type phy_type)
35 : socket_(socket_fd),
36 phy_type_(phy_type),
37 size_bytes_(std::make_shared<std::vector<uint8_t>>(kSizeBytes)) {}
38
Tick()39 void LinkLayerSocketDevice::Tick() {
40 if (receiving_size_) {
41 ssize_t bytes_received =
42 socket_->Recv(size_bytes_->data() + offset_, kSizeBytes);
43 if (bytes_received <= 0) {
44 if (errno == EAGAIN || errno == EWOULDBLOCK) {
45 // Nothing available yet.
46 // LOG_DEBUG("Nothing available yet...");
47 return;
48 }
49 LOG_INFO("Closing socket, received: %zd, %s", bytes_received,
50 strerror(errno));
51 Close();
52 return;
53 }
54 if ((size_t)bytes_received < bytes_left_) {
55 bytes_left_ -= bytes_received;
56 offset_ += bytes_received;
57 return;
58 }
59 bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> size(
60 {bluetooth::packet::View(size_bytes_, 0, kSizeBytes)});
61 bytes_left_ = size.begin().extract<uint32_t>();
62 received_ = std::make_shared<std::vector<uint8_t>>(bytes_left_);
63 offset_ = 0;
64 receiving_size_ = false;
65 }
66 ssize_t bytes_received =
67 socket_->Recv(received_->data() + offset_, bytes_left_);
68 if (bytes_received <= 0) {
69 if (errno == EAGAIN || errno == EWOULDBLOCK) {
70 // Nothing available yet.
71 // LOG_DEBUG("Nothing available yet...");
72 return;
73 }
74 LOG_INFO("Closing socket, received: %zd, %s", bytes_received,
75 strerror(errno));
76 Close();
77 return;
78 }
79 if ((size_t)bytes_received < bytes_left_) {
80 bytes_left_ -= bytes_received;
81 offset_ += bytes_received;
82 return;
83 }
84 bytes_left_ = kSizeBytes;
85 offset_ = 0;
86 receiving_size_ = true;
87 SendLinkLayerPacket(*received_, phy_type_);
88 }
89
Close()90 void LinkLayerSocketDevice::Close() {
91 if (socket_) {
92 socket_->Close();
93 }
94 Device::Close();
95 }
96
ReceiveLinkLayerPacket(model::packets::LinkLayerPacketView packet,Phy::Type,int8_t)97 void LinkLayerSocketDevice::ReceiveLinkLayerPacket(
98 model::packets::LinkLayerPacketView packet, Phy::Type /*type*/,
99 int8_t /*rssi*/) {
100 auto size_packet = bluetooth::packet::RawBuilder();
101 size_packet.AddOctets4(packet.size());
102 std::vector<uint8_t> size_bytes;
103 bluetooth::packet::BitInserter bit_inserter(size_bytes);
104 size_packet.Serialize(bit_inserter);
105
106 if (socket_->Send(size_bytes.data(), size_bytes.size()) == kSizeBytes) {
107 std::vector<uint8_t> payload_bytes{packet.begin(), packet.end()};
108 socket_->Send(payload_bytes.data(), payload_bytes.size());
109 }
110 }
111
112 } // namespace rootcanal
113