| /* |
| * Copyright 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "model/devices/link_layer_socket_device.h" |
| |
| #include <packet_runtime.h> |
| |
| #include <cerrno> |
| #include <cstdint> |
| #include <cstring> |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "log.h" |
| #include "model/devices/device.h" |
| #include "packets/link_layer_packets.h" |
| #include "phy.h" |
| |
| using std::vector; |
| |
| namespace rootcanal { |
| |
| LinkLayerSocketDevice::LinkLayerSocketDevice( |
| std::shared_ptr<AsyncDataChannel> socket_fd, Phy::Type phy_type) |
| : socket_(socket_fd), |
| phy_type_(phy_type), |
| size_bytes_(std::make_shared<std::vector<uint8_t>>(kSizeBytes)) {} |
| |
| void LinkLayerSocketDevice::Tick() { |
| if (receiving_size_) { |
| ssize_t bytes_received = |
| socket_->Recv(size_bytes_->data() + offset_, kSizeBytes); |
| if (bytes_received <= 0) { |
| if (errno == EAGAIN || errno == EWOULDBLOCK) { |
| // Nothing available yet. |
| // DEBUG("Nothing available yet..."); |
| return; |
| } |
| INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno)); |
| Close(); |
| return; |
| } |
| if ((size_t)bytes_received < bytes_left_) { |
| bytes_left_ -= bytes_received; |
| offset_ += bytes_received; |
| return; |
| } |
| pdl::packet::slice size(std::move(size_bytes_)); |
| bytes_left_ = size.read_le<uint32_t>(); |
| received_ = std::make_shared<std::vector<uint8_t>>(bytes_left_); |
| offset_ = 0; |
| receiving_size_ = false; |
| } |
| ssize_t bytes_received = |
| socket_->Recv(received_->data() + offset_, bytes_left_); |
| if (bytes_received <= 0) { |
| if (errno == EAGAIN || errno == EWOULDBLOCK) { |
| // Nothing available yet. |
| // DEBUG("Nothing available yet..."); |
| return; |
| } |
| INFO("Closing socket, received: {}, {}", bytes_received, strerror(errno)); |
| Close(); |
| return; |
| } |
| if ((size_t)bytes_received < bytes_left_) { |
| bytes_left_ -= bytes_received; |
| offset_ += bytes_received; |
| return; |
| } |
| bytes_left_ = kSizeBytes; |
| offset_ = 0; |
| receiving_size_ = true; |
| SendLinkLayerPacket(*received_, phy_type_); |
| } |
| |
| void LinkLayerSocketDevice::Close() { |
| if (socket_) { |
| socket_->Close(); |
| } |
| Device::Close(); |
| } |
| |
| void LinkLayerSocketDevice::ReceiveLinkLayerPacket( |
| model::packets::LinkLayerPacketView packet, Phy::Type /*type*/, |
| int8_t /*rssi*/) { |
| std::vector<uint8_t> packet_bytes = packet.bytes().bytes(); |
| std::vector<uint8_t> size_bytes; |
| pdl::packet::Builder::write_le<uint32_t>(size_bytes, packet_bytes.size()); |
| |
| if (socket_->Send(size_bytes.data(), size_bytes.size()) == kSizeBytes) { |
| socket_->Send(packet_bytes.data(), packet_bytes.size()); |
| } |
| } |
| |
| } // namespace rootcanal |