blob: 3481b9474a51a2d3735b500c7a32921b2c25e7ef [file] [log] [blame]
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 University of California, Los Angeles
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
*/
#include "ndn-ip-face-stack.hpp"
#include "ndn-tcp-face.hpp"
#include "ndn-udp-face.hpp"
#include "ns3/ndn-l3-protocol.hpp"
#include "ns3/log.h"
#include "ns3/assert.h"
#include "ns3/packet.h"
#include "ns3/boolean.h"
#include "ns3/socket.h"
#include "ns3/tcp-socket-factory.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/simulator.h"
NS_LOG_COMPONENT_DEFINE("ndn.IpFaceStack");
namespace ns3 {
namespace ndn {
NS_OBJECT_ENSURE_REGISTERED(IpFaceStack);
const Callback<void, Ptr<Face>> IpFaceStack::NULL_CREATE_CALLBACK =
MakeNullCallback<void, Ptr<Face>>();
TypeId
IpFaceStack::GetTypeId(void)
{
static TypeId tid =
TypeId("ns3::ndn::IpFaceStack")
.SetGroupName("Ndn")
.SetParent<Object>()
.AddConstructor<IpFaceStack>()
.AddAttribute("EnableTCP", "Enable ability to create TCP faces", BooleanValue(true),
MakeBooleanAccessor(&IpFaceStack::m_enableTcp), MakeBooleanChecker())
.AddAttribute("EnableUDP", "Enable ability to create UDP faces", BooleanValue(true),
MakeBooleanAccessor(&IpFaceStack::m_enableUdp), MakeBooleanChecker());
return tid;
}
IpFaceStack::IpFaceStack()
{
}
IpFaceStack::~IpFaceStack()
{
}
void
IpFaceStack::NotifyNewAggregate()
{
if (m_node == 0) {
m_node = GetObject<Node>();
if (m_node != 0) {
Simulator::ScheduleWithContext(m_node->GetId(), Seconds(0.1), &IpFaceStack::StartServer,
this);
}
}
}
// Application Methods
void
IpFaceStack::StartServer() // Called at time specified by Start
{
NS_LOG_FUNCTION(this);
if (m_enableTcp) {
m_tcpServer = Socket::CreateSocket(m_node, TcpSocketFactory::GetTypeId());
m_tcpServer->Bind(InetSocketAddress(Ipv4Address::GetAny(), L3Protocol::IP_STACK_PORT));
m_tcpServer->Listen();
m_tcpServer->SetAcceptCallback(MakeCallback(&IpFaceStack::OnTcpConnectionRequest, this),
MakeCallback(&IpFaceStack::OnTcpConnectionAccept, this));
}
if (m_enableUdp) {
m_udpServer = Socket::CreateSocket(m_node, UdpSocketFactory::GetTypeId());
m_udpServer->Bind(InetSocketAddress(Ipv4Address::GetAny(), L3Protocol::IP_STACK_PORT));
m_udpServer->SetRecvCallback(MakeCallback(&IpFaceStack::OnUdpPacket, this));
}
}
bool
IpFaceStack::OnTcpConnectionRequest(Ptr<Socket> sock, const Address& addr)
{
NS_LOG_FUNCTION(this << sock << InetSocketAddress::ConvertFrom(addr));
return true; // accept all connections from anybody
}
void
IpFaceStack::OnTcpConnectionAccept(Ptr<Socket> socket, const Address& addr)
{
NS_LOG_FUNCTION(this << socket << InetSocketAddress::ConvertFrom(addr));
Ptr<L3Protocol> ndn = m_node->GetObject<L3Protocol>();
Ptr<TcpFace> face =
CreateObject<TcpFace>(m_node, socket, InetSocketAddress::ConvertFrom(addr).GetIpv4());
ndn->AddFace(face);
face->SetUp(true);
socket->SetCloseCallbacks(MakeCallback(&TcpFace::OnTcpConnectionClosed, face),
MakeCallback(&TcpFace::OnTcpConnectionClosed, face));
}
void
IpFaceStack::OnUdpPacket(Ptr<Socket> socket)
{
NS_LOG_FUNCTION(this << socket);
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom(from))) {
Ptr<UdpFace> face = CreateOrGetUdpFace(InetSocketAddress::ConvertFrom(from).GetIpv4());
face->ReceiveFromUdp(packet);
}
}
Ptr<TcpFace>
IpFaceStack::GetTcpFaceByAddress(const Ipv4Address& address)
{
TcpFaceMap::iterator i = m_tcpFaceMap.find(address);
if (i != m_tcpFaceMap.end())
return i->second;
else
return 0;
}
void
IpFaceStack::DestroyTcpFace(Ptr<TcpFace> face)
{
m_tcpFaceMap.erase(face->GetAddress());
}
Ptr<UdpFace>
IpFaceStack::GetUdpFaceByAddress(const Ipv4Address& address)
{
UdpFaceMap::iterator i = m_udpFaceMap.find(address);
if (i != m_udpFaceMap.end())
return i->second;
else
return 0;
}
Ptr<TcpFace>
IpFaceStack::CreateOrGetTcpFace(Ipv4Address address, Callback<void, Ptr<Face>> onCreate)
{
NS_LOG_FUNCTION(address);
TcpFaceMap::iterator i = m_tcpFaceMap.find(address);
if (i != m_tcpFaceMap.end())
return i->second;
Ptr<Socket> socket = Socket::CreateSocket(m_node, TcpSocketFactory::GetTypeId());
Ptr<TcpFace> face = CreateObject<TcpFace>(m_node, socket, address);
face->SetCreateCallback(onCreate);
socket->SetConnectCallback(MakeCallback(&TcpFace::OnConnect, face),
MakeNullCallback<void, Ptr<Socket>>());
socket->Connect(InetSocketAddress(address, L3Protocol::IP_STACK_PORT));
m_tcpFaceMap.insert(std::make_pair(address, face));
return face;
}
Ptr<UdpFace>
IpFaceStack::CreateOrGetUdpFace(Ipv4Address address)
{
NS_LOG_FUNCTION(address);
UdpFaceMap::iterator i = m_udpFaceMap.find(address);
if (i != m_udpFaceMap.end())
return i->second;
Ptr<Socket> socket = Socket::CreateSocket(m_node, UdpSocketFactory::GetTypeId());
socket->Bind(InetSocketAddress(Ipv4Address::GetAny(),
L3Protocol::IP_STACK_PORT)); // not sure if it going to work...
// socket->Bind ();
socket->Connect(InetSocketAddress(address, L3Protocol::IP_STACK_PORT));
Ptr<UdpFace> face = CreateObject<UdpFace>(m_node, socket, address);
Ptr<L3Protocol> ndn = m_node->GetObject<L3Protocol>();
ndn->AddFace(face);
face->SetUp(true);
m_udpFaceMap.insert(std::make_pair(address, face));
return face;
}
} // namespace ndn
} // namespace ns3