/* * 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 #include #include #include #include #include #include #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 socket_fd, Phy::Type phy_type) : socket_(socket_fd), phy_type_(phy_type), size_bytes_(std::make_shared>(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(); received_ = std::make_shared>(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 packet_bytes = packet.bytes().bytes(); std::vector size_bytes; pdl::packet::Builder::write_le(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