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(std::shared_ptr<AsyncDataChannel> socket_fd,
38                                              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 = socket_->Recv(size_bytes_->data() + offset_, kSizeBytes);
46     if (bytes_received <= 0) {
47       if (errno == EAGAIN || errno == EWOULDBLOCK) {
48         // Nothing available yet.
49         // DEBUG("Nothing available yet...");
50         return;
51       }
52       INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno));
53       Close();
54       return;
55     }
56     if ((size_t)bytes_received < bytes_left_) {
57       bytes_left_ -= bytes_received;
58       offset_ += bytes_received;
59       return;
60     }
61     pdl::packet::slice size(std::move(size_bytes_));
62     bytes_left_ = size.read_le<uint32_t>();
63     received_ = std::make_shared<std::vector<uint8_t>>(bytes_left_);
64     offset_ = 0;
65     receiving_size_ = false;
66   }
67   ssize_t bytes_received = socket_->Recv(received_->data() + offset_, bytes_left_);
68   if (bytes_received <= 0) {
69     if (errno == EAGAIN || errno == EWOULDBLOCK) {
70       // Nothing available yet.
71       // DEBUG("Nothing available yet...");
72       return;
73     }
74     INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno));
75     Close();
76     return;
77   }
78   if ((size_t)bytes_received < bytes_left_) {
79     bytes_left_ -= bytes_received;
80     offset_ += bytes_received;
81     return;
82   }
83   bytes_left_ = kSizeBytes;
84   offset_ = 0;
85   receiving_size_ = true;
86   SendLinkLayerPacket(*received_, phy_type_);
87 }
88 
Close()89 void LinkLayerSocketDevice::Close() {
90   if (socket_) {
91     socket_->Close();
92   }
93   Device::Close();
94 }
95 
ReceiveLinkLayerPacket(model::packets::LinkLayerPacketView packet,Phy::Type,int8_t)96 void LinkLayerSocketDevice::ReceiveLinkLayerPacket(model::packets::LinkLayerPacketView packet,
97                                                    Phy::Type /*type*/, int8_t /*rssi*/) {
98   std::vector<uint8_t> packet_bytes = packet.bytes().bytes();
99   std::vector<uint8_t> size_bytes;
100   pdl::packet::Builder::write_le<uint32_t>(size_bytes, packet_bytes.size());
101 
102   if (socket_->Send(size_bytes.data(), size_bytes.size()) == kSizeBytes) {
103     socket_->Send(packet_bytes.data(), packet_bytes.size());
104   }
105 }
106 
107 }  // namespace rootcanal
108