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
~SocketManager()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
SendDatagram(const NemoraDatagram * bcast)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
CloseSocketSafely(int fd)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
TrackSocket(int fd)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