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