1*14fe6698SNan Zhou // Copyright 2021 Google LLC 2*14fe6698SNan Zhou // 3*14fe6698SNan Zhou // Licensed under the Apache License, Version 2.0 (the "License"); 4*14fe6698SNan Zhou // you may not use this file except in compliance with the License. 5*14fe6698SNan Zhou // You may obtain a copy of the License at 6*14fe6698SNan Zhou // 7*14fe6698SNan Zhou // http://www.apache.org/licenses/LICENSE-2.0 8*14fe6698SNan Zhou // 9*14fe6698SNan Zhou // Unless required by applicable law or agreed to in writing, software 10*14fe6698SNan Zhou // distributed under the License is distributed on an "AS IS" BASIS, 11*14fe6698SNan Zhou // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*14fe6698SNan Zhou // See the License for the specific language governing permissions and 13*14fe6698SNan Zhou // limitations under the License. 14*14fe6698SNan Zhou 15*14fe6698SNan Zhou #include "socket_manager.hpp" 16*14fe6698SNan Zhou 17*14fe6698SNan Zhou #include "serializer.hpp" 18*14fe6698SNan Zhou 19*14fe6698SNan Zhou #include <errno.h> 20*14fe6698SNan Zhou #include <fmt/format.h> 21*14fe6698SNan Zhou #include <sys/socket.h> 22*14fe6698SNan Zhou #include <unistd.h> 23*14fe6698SNan Zhou 24*14fe6698SNan Zhou #include <phosphor-logging/log.hpp> 25*14fe6698SNan Zhou 26*14fe6698SNan Zhou #include <cstring> 27*14fe6698SNan Zhou 28*14fe6698SNan Zhou using fmt::format; 29*14fe6698SNan Zhou using phosphor::logging::level; 30*14fe6698SNan Zhou using phosphor::logging::log; 31*14fe6698SNan Zhou 32*14fe6698SNan Zhou SocketManager::~SocketManager() 33*14fe6698SNan Zhou { 34*14fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 35*14fe6698SNan Zhou for (auto fd : open_sockets_) 36*14fe6698SNan Zhou { 37*14fe6698SNan Zhou close(fd); 38*14fe6698SNan Zhou } 39*14fe6698SNan Zhou } 40*14fe6698SNan Zhou 41*14fe6698SNan Zhou void SocketManager::SendDatagram(const NemoraDatagram* bcast) 42*14fe6698SNan Zhou { 43*14fe6698SNan Zhou std::string serialized = Serializer::Serialize(bcast); 44*14fe6698SNan Zhou 45*14fe6698SNan Zhou // Create socket 46*14fe6698SNan Zhou auto fd = socket(AF_INET6, SOCK_DGRAM, 0); 47*14fe6698SNan Zhou if (fd < 0) 48*14fe6698SNan Zhou { 49*14fe6698SNan Zhou log<level::ERR>("SocketManager::SendDatagram: Couldn't open socket"); 50*14fe6698SNan Zhou } 51*14fe6698SNan Zhou TrackSocket(fd); 52*14fe6698SNan Zhou 53*14fe6698SNan Zhou // Because we aren't sure whether the v6 or v4 target IP will be present, 54*14fe6698SNan Zhou // we send UDP packets to both. This puts us at feature parity with EC. 55*14fe6698SNan Zhou 56*14fe6698SNan Zhou // Send serialized data (v6) 57*14fe6698SNan Zhou auto addr6 = reinterpret_cast<const sockaddr*>(&bcast->destination6); 58*14fe6698SNan Zhou auto err = sendto(fd, serialized.c_str(), serialized.length(), 0, addr6, 59*14fe6698SNan Zhou sizeof(bcast->destination6)); 60*14fe6698SNan Zhou if (err < 0) 61*14fe6698SNan Zhou { 62*14fe6698SNan Zhou log<level::ERR>(format("SocketManager::SendDatagram: Couldn't sendto " 63*14fe6698SNan Zhou "socket (IPv6): {}", 64*14fe6698SNan Zhou std::strerror(errno)) 65*14fe6698SNan Zhou .c_str()); 66*14fe6698SNan Zhou } 67*14fe6698SNan Zhou 68*14fe6698SNan Zhou // Send serialized data (v4) 69*14fe6698SNan Zhou auto addr4 = reinterpret_cast<const sockaddr*>(&bcast->destination); 70*14fe6698SNan Zhou err = sendto(fd, serialized.c_str(), serialized.length(), 0, addr4, 71*14fe6698SNan Zhou sizeof(bcast->destination)); 72*14fe6698SNan Zhou if (err < 0) 73*14fe6698SNan Zhou { 74*14fe6698SNan Zhou log<level::ERR>(format("SocketManager::SendDatagram: Couldn't sendto " 75*14fe6698SNan Zhou "socket (IPv4): {}", 76*14fe6698SNan Zhou std::strerror(errno)) 77*14fe6698SNan Zhou .c_str()); 78*14fe6698SNan Zhou } 79*14fe6698SNan Zhou 80*14fe6698SNan Zhou CloseSocketSafely(fd); 81*14fe6698SNan Zhou } 82*14fe6698SNan Zhou 83*14fe6698SNan Zhou void SocketManager::CloseSocketSafely(int fd) 84*14fe6698SNan Zhou { 85*14fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 86*14fe6698SNan Zhou if (open_sockets_.find(fd) != open_sockets_.end()) 87*14fe6698SNan Zhou { 88*14fe6698SNan Zhou close(fd); 89*14fe6698SNan Zhou open_sockets_.erase(fd); 90*14fe6698SNan Zhou } 91*14fe6698SNan Zhou } 92*14fe6698SNan Zhou 93*14fe6698SNan Zhou void SocketManager::TrackSocket(int fd) 94*14fe6698SNan Zhou { 95*14fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 96*14fe6698SNan Zhou open_sockets_.insert(fd); 97*14fe6698SNan Zhou } 98