114fe6698SNan Zhou // Copyright 2021 Google LLC 214fe6698SNan Zhou // 314fe6698SNan Zhou // Licensed under the Apache License, Version 2.0 (the "License"); 414fe6698SNan Zhou // you may not use this file except in compliance with the License. 514fe6698SNan Zhou // You may obtain a copy of the License at 614fe6698SNan Zhou // 714fe6698SNan Zhou // http://www.apache.org/licenses/LICENSE-2.0 814fe6698SNan Zhou // 914fe6698SNan Zhou // Unless required by applicable law or agreed to in writing, software 1014fe6698SNan Zhou // distributed under the License is distributed on an "AS IS" BASIS, 1114fe6698SNan Zhou // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1214fe6698SNan Zhou // See the License for the specific language governing permissions and 1314fe6698SNan Zhou // limitations under the License. 1414fe6698SNan Zhou 1514fe6698SNan Zhou #include "socket_manager.hpp" 1614fe6698SNan Zhou 1714fe6698SNan Zhou #include "serializer.hpp" 1814fe6698SNan Zhou 1914fe6698SNan Zhou #include <errno.h> 2014fe6698SNan Zhou #include <sys/socket.h> 2114fe6698SNan Zhou #include <unistd.h> 2214fe6698SNan Zhou 2314fe6698SNan Zhou #include <phosphor-logging/log.hpp> 2414fe6698SNan Zhou 2514fe6698SNan Zhou #include <cstring> 26*bb53161dSWilly Tu #include <format> 2714fe6698SNan Zhou 2814fe6698SNan Zhou using phosphor::logging::level; 2914fe6698SNan Zhou using phosphor::logging::log; 3014fe6698SNan Zhou 3114fe6698SNan Zhou SocketManager::~SocketManager() 3214fe6698SNan Zhou { 3314fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 3414fe6698SNan Zhou for (auto fd : open_sockets_) 3514fe6698SNan Zhou { 3614fe6698SNan Zhou close(fd); 3714fe6698SNan Zhou } 3814fe6698SNan Zhou } 3914fe6698SNan Zhou 4014fe6698SNan Zhou void SocketManager::SendDatagram(const NemoraDatagram* bcast) 4114fe6698SNan Zhou { 4214fe6698SNan Zhou std::string serialized = Serializer::Serialize(bcast); 4314fe6698SNan Zhou 4414fe6698SNan Zhou // Create socket 4514fe6698SNan Zhou auto fd = socket(AF_INET6, SOCK_DGRAM, 0); 4614fe6698SNan Zhou if (fd < 0) 4714fe6698SNan Zhou { 4814fe6698SNan Zhou log<level::ERR>("SocketManager::SendDatagram: Couldn't open socket"); 4914fe6698SNan Zhou } 5014fe6698SNan Zhou TrackSocket(fd); 5114fe6698SNan Zhou 5214fe6698SNan Zhou // Because we aren't sure whether the v6 or v4 target IP will be present, 5314fe6698SNan Zhou // we send UDP packets to both. This puts us at feature parity with EC. 5414fe6698SNan Zhou 5514fe6698SNan Zhou // Send serialized data (v6) 5614fe6698SNan Zhou auto addr6 = reinterpret_cast<const sockaddr*>(&bcast->destination6); 5714fe6698SNan Zhou auto err = sendto(fd, serialized.c_str(), serialized.length(), 0, addr6, 5814fe6698SNan Zhou sizeof(bcast->destination6)); 5914fe6698SNan Zhou if (err < 0) 6014fe6698SNan Zhou { 61*bb53161dSWilly Tu log<level::ERR>( 62*bb53161dSWilly Tu std::format("SocketManager::SendDatagram: Couldn't sendto " 6314fe6698SNan Zhou "socket (IPv6): {}", 6414fe6698SNan Zhou std::strerror(errno)) 6514fe6698SNan Zhou .c_str()); 6614fe6698SNan Zhou } 6714fe6698SNan Zhou 6814fe6698SNan Zhou // Send serialized data (v4) 6914fe6698SNan Zhou auto addr4 = reinterpret_cast<const sockaddr*>(&bcast->destination); 7014fe6698SNan Zhou err = sendto(fd, serialized.c_str(), serialized.length(), 0, addr4, 7114fe6698SNan Zhou sizeof(bcast->destination)); 7214fe6698SNan Zhou if (err < 0) 7314fe6698SNan Zhou { 74*bb53161dSWilly Tu log<level::ERR>( 75*bb53161dSWilly Tu std::format("SocketManager::SendDatagram: Couldn't sendto " 7614fe6698SNan Zhou "socket (IPv4): {}", 7714fe6698SNan Zhou std::strerror(errno)) 7814fe6698SNan Zhou .c_str()); 7914fe6698SNan Zhou } 8014fe6698SNan Zhou 8114fe6698SNan Zhou CloseSocketSafely(fd); 8214fe6698SNan Zhou } 8314fe6698SNan Zhou 8414fe6698SNan Zhou void SocketManager::CloseSocketSafely(int fd) 8514fe6698SNan Zhou { 8614fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 8714fe6698SNan Zhou if (open_sockets_.find(fd) != open_sockets_.end()) 8814fe6698SNan Zhou { 8914fe6698SNan Zhou close(fd); 9014fe6698SNan Zhou open_sockets_.erase(fd); 9114fe6698SNan Zhou } 9214fe6698SNan Zhou } 9314fe6698SNan Zhou 9414fe6698SNan Zhou void SocketManager::TrackSocket(int fd) 9514fe6698SNan Zhou { 9614fe6698SNan Zhou std::lock_guard<std::mutex> lock(open_sockets_lock_); 9714fe6698SNan Zhou open_sockets_.insert(fd); 9814fe6698SNan Zhou } 99