xref: /openbmc/google-misc/subprojects/nemora-postd/src/socket_manager.cpp (revision bb53161d64a2af77a2a396ee4370b5c1255b73f9)
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