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 "model/devices/link_layer_socket_device.h"
18
19 #include <packet_runtime.h>
20
21 #include <cerrno>
22 #include <cstdint>
23 #include <cstring>
24 #include <memory>
25 #include <utility>
26 #include <vector>
27
28 #include "log.h"
29 #include "model/devices/device.h"
30 #include "packets/link_layer_packets.h"
31 #include "phy.h"
32
33 using std::vector;
34
35 namespace rootcanal {
36
LinkLayerSocketDevice(std::shared_ptr<AsyncDataChannel> socket_fd,Phy::Type phy_type)37 LinkLayerSocketDevice::LinkLayerSocketDevice(
38 std::shared_ptr<AsyncDataChannel> socket_fd, Phy::Type phy_type)
39 : socket_(socket_fd),
40 phy_type_(phy_type),
41 size_bytes_(std::make_shared<std::vector<uint8_t>>(kSizeBytes)) {}
42
Tick()43 void LinkLayerSocketDevice::Tick() {
44 if (receiving_size_) {
45 ssize_t bytes_received =
46 socket_->Recv(size_bytes_->data() + offset_, kSizeBytes);
47 if (bytes_received <= 0) {
48 if (errno == EAGAIN || errno == EWOULDBLOCK) {
49 // Nothing available yet.
50 // DEBUG("Nothing available yet...");
51 return;
52 }
53 INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno));
54 Close();
55 return;
56 }
57 if ((size_t)bytes_received < bytes_left_) {
58 bytes_left_ -= bytes_received;
59 offset_ += bytes_received;
60 return;
61 }
62 pdl::packet::slice size(std::move(size_bytes_));
63 bytes_left_ = size.read_le<uint32_t>();
64 received_ = std::make_shared<std::vector<uint8_t>>(bytes_left_);
65 offset_ = 0;
66 receiving_size_ = false;
67 }
68 ssize_t bytes_received =
69 socket_->Recv(received_->data() + offset_, bytes_left_);
70 if (bytes_received <= 0) {
71 if (errno == EAGAIN || errno == EWOULDBLOCK) {
72 // Nothing available yet.
73 // DEBUG("Nothing available yet...");
74 return;
75 }
76 INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno));
77 Close();
78 return;
79 }
80 if ((size_t)bytes_received < bytes_left_) {
81 bytes_left_ -= bytes_received;
82 offset_ += bytes_received;
83 return;
84 }
85 bytes_left_ = kSizeBytes;
86 offset_ = 0;
87 receiving_size_ = true;
88 SendLinkLayerPacket(*received_, phy_type_);
89 }
90
Close()91 void LinkLayerSocketDevice::Close() {
92 if (socket_) {
93 socket_->Close();
94 }
95 Device::Close();
96 }
97
ReceiveLinkLayerPacket(model::packets::LinkLayerPacketView packet,Phy::Type,int8_t)98 void LinkLayerSocketDevice::ReceiveLinkLayerPacket(
99 model::packets::LinkLayerPacketView packet, Phy::Type /*type*/,
100 int8_t /*rssi*/) {
101 std::vector<uint8_t> packet_bytes = packet.bytes().bytes();
102 std::vector<uint8_t> size_bytes;
103 pdl::packet::Builder::write_le<uint32_t>(size_bytes, packet_bytes.size());
104
105 if (socket_->Send(size_bytes.data(), size_bytes.size()) == kSizeBytes) {
106 socket_->Send(packet_bytes.data(), packet_bytes.size());
107 }
108 }
109
110 } // namespace rootcanal
111