applications: Add attribute in UdpEchoServer to specify local address on which to bind to

This commit is contained in:
Sébastien Deronne
2024-06-16 10:05:39 +02:00
parent fbb4d250f9
commit 4f09959a76
5 changed files with 47 additions and 20 deletions

View File

@@ -22,6 +22,12 @@ UdpEchoServerHelper::UdpEchoServerHelper(uint16_t port)
SetAttribute("Port", UintegerValue(port));
}
UdpEchoServerHelper::UdpEchoServerHelper(const Address& address)
: ApplicationHelper(UdpEchoServer::GetTypeId())
{
SetAttribute("Local", AddressValue(address));
}
UdpEchoClientHelper::UdpEchoClientHelper(const Address& address, uint16_t port)
: UdpEchoClientHelper(addressUtils::ConvertToSocketAddress(address, port))
{

View File

@@ -31,6 +31,14 @@ class UdpEchoServerHelper : public ApplicationHelper
* \param port The port the server will wait on for incoming packets
*/
UdpEchoServerHelper(uint16_t port);
/**
* Create UdpEchoServerHelper which will make life easier for people trying
* to set up simulations with echos.
*
* \param address The address the server will bind to
*/
UdpEchoServerHelper(const Address& address);
};
/**

View File

@@ -35,6 +35,12 @@ UdpEchoServer::GetTypeId()
.SetParent<Application>()
.SetGroupName("Applications")
.AddConstructor<UdpEchoServer>()
.AddAttribute("Local",
"The Address on which to Bind the rx socket. "
"If it is not specified, it will listen to any address.",
AddressValue(),
MakeAddressAccessor(&UdpEchoServer::m_local),
MakeAddressChecker())
.AddAttribute("Port",
"Port on which we listen for incoming packets.",
UintegerValue(9),
@@ -58,6 +64,8 @@ UdpEchoServer::GetTypeId()
}
UdpEchoServer::UdpEchoServer()
: m_socket{nullptr},
m_socket6{nullptr}
{
NS_LOG_FUNCTION(this);
}
@@ -76,9 +84,13 @@ UdpEchoServer::StartApplication()
if (!m_socket)
{
TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
auto tid = TypeId::LookupByName("ns3::UdpSocketFactory");
m_socket = Socket::CreateSocket(GetNode(), tid);
InetSocketAddress local = InetSocketAddress(Ipv4Address::GetAny(), m_port);
auto local = m_local;
if (local.IsInvalid())
{
local = InetSocketAddress(Ipv4Address::GetAny(), m_port);
}
if (m_socket->Bind(local) == -1)
{
NS_FATAL_ERROR("Failed to bind socket");
@@ -96,35 +108,36 @@ UdpEchoServer::StartApplication()
NS_FATAL_ERROR("Error: Failed to join multicast group");
}
}
m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets.
m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
}
if (!m_socket6)
if (m_local.IsInvalid() && !m_socket6)
{
TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
// local address is not specified, so create another socket to also listen to all IPv6
// addresses
auto tid = TypeId::LookupByName("ns3::UdpSocketFactory");
m_socket6 = Socket::CreateSocket(GetNode(), tid);
Inet6SocketAddress local6 = Inet6SocketAddress(Ipv6Address::GetAny(), m_port);
if (m_socket6->Bind(local6) == -1)
auto local = Inet6SocketAddress(Ipv6Address::GetAny(), m_port);
if (m_socket6->Bind(local) == -1)
{
NS_FATAL_ERROR("Failed to bind socket");
}
if (addressUtils::IsMulticast(local6))
if (addressUtils::IsMulticast(local))
{
Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket>(m_socket6);
if (udpSocket)
{
// equivalent to setsockopt (MCAST_JOIN_GROUP)
udpSocket->MulticastJoinGroup(0, local6);
udpSocket->MulticastJoinGroup(0, local);
}
else
{
NS_FATAL_ERROR("Error: Failed to join multicast group");
}
}
m_socket6->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
}
m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets.
m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
m_socket6->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
}
void
@@ -149,11 +162,10 @@ UdpEchoServer::HandleRead(Ptr<Socket> socket)
{
NS_LOG_FUNCTION(this << socket);
Ptr<Packet> packet;
Address from;
Address localAddress;
while ((packet = socket->RecvFrom(from)))
while (auto packet = socket->RecvFrom(from))
{
Address localAddress;
socket->GetSockName(localAddress);
m_rxTrace(packet);
m_rxTraceWithAddresses(packet, from, localAddress);

View File

@@ -54,11 +54,12 @@ class UdpEchoServer : public Application
*/
void HandleRead(Ptr<Socket> socket);
uint16_t m_port; //!< Port on which we listen for incoming packets.
uint16_t
m_port; //!< Port on which we listen for incoming packets if local address is not specified
uint8_t m_tos; //!< The packets Type of Service
Ptr<Socket> m_socket; //!< IPv4 Socket
Ptr<Socket> m_socket6; //!< IPv6 Socket
Address m_local; //!< local multicast address
Ptr<Socket> m_socket; //!< Socket
Ptr<Socket> m_socket6; //!< IPv6 Socket (used if only port is specified)
Address m_local; //!< Local address to bind to (address and port)
/// Callbacks for tracing the packet Rx events
TracedCallback<Ptr<const Packet>> m_rxTrace;

View File

@@ -310,7 +310,7 @@ UdpEchoClientSetFillTestCase::DoRun()
Ipv4InterfaceContainer interfaces = ipv4.Assign(d);
uint16_t port = 5000;
UdpEchoServerHelper echoServer(port);
UdpEchoServerHelper echoServer(InetSocketAddress(Ipv4Address::GetAny(), port));
ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));
serverApps.Start(Seconds(1.0));
serverApps.Stop(Seconds(10.0));