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