#include #include #include #include #include #include #include #include #include #include "ns3/core-module.h" #include "ns3/helper-module.h" #include "ns3/node-module.h" #include "ns3/global-route-manager.h" #include "ns3/simulator-module.h" using namespace ns3; class Atag : public Tag { public: static TypeId GetTypeId(void); virtual TypeId GetInstanceTypeId(void) const; virtual uint32_t GetSerializedSize(void) const; virtual void Serialize(TagBuffer) const; virtual void Deserialize(TagBuffer); void Print (std::ostream &os) const; void SetIntValue(uint32_t); uint32_t GetIntValue(void) const; void SetStrValue(const std::string &s); std::string GetStrValue(void) const; private: uint32_t int_value; std::string str_value; const static bool debug = 0; }; TypeId Atag::GetTypeId(void) { static TypeId tid = TypeId("ns3::Atag") .AddConstructor() // had to add this to get Socket::PrintTags to work .SetParent(); // didn't do accessors how? return tid; } TypeId Atag::GetInstanceTypeId(void) const { return GetTypeId(); } uint32_t Atag::GetSerializedSize (void) const { return 2*sizeof(uint32_t) + str_value.size(); } void Atag::Serialize (TagBuffer i) const { if (debug) std::cout << "Atag::Serialize() called" << std::endl; if (debug) std::cout << " int_value = " << int_value << std::endl; i.WriteU32 (int_value); uint32_t str_len = str_value.size(); if (debug) std::cout << " str_len = " << str_len << std::endl; i.WriteU32 (str_len); for (int j = 0; j < str_value.size(); j++) { if (debug) std::cout << " str_value[" << j << "] = " << str_value[j] << std::endl; i.WriteU8(str_value[j]); // NOTE: assumes 8bit chars. } } void Atag::Deserialize (TagBuffer i) { if (debug) std::cout << "Atag::Deserialize() called" << std::endl; int_value = i.ReadU32 (); if (debug) std::cout << " int_value = " << int_value << std::endl; uint32_t str_len = i.ReadU32(); if (debug) std::cout << " str_len = " << str_len << std::endl; str_value.reserve(str_len); for (int j = 0; j < str_len; j++) { char v = i.ReadU8(); str_value.push_back(v); if (debug) std::cout << " str_value[" << j << "] = " << str_value[j] << std::endl; } if (debug) std::cout << "string is " << str_value << std::endl; } void Atag::SetIntValue(uint32_t v_) { int_value = v_; } uint32_t Atag::GetIntValue(void) const { return int_value; } void Atag::SetStrValue(const std::string &s) { str_value = s; } std::string Atag::GetStrValue(void) const { return str_value; } void Atag::Print (std::ostream &os) const { os << "(Atag=" << str_value << ":" << int_value << ")" << std::endl; } class ArchHeader : public Header { public: virtual uint32_t GetSerializedSize(void) const; virtual void Serialize(Buffer::Iterator) const; virtual uint32_t Deserialize(Buffer::Iterator); virtual void Print(std::ostream &) const; static TypeId GetTypeId(void); virtual TypeId GetInstanceTypeId(void) const; void SetIntValue(uint32_t); uint32_t GetIntValue(void) const; void SetStrValue(const std::string &s); std::string GetStrValue(void) const; private: uint32_t int_value; std::string str_value; const static bool debug = 0; }; TypeId ArchHeader::GetTypeId(void) { static TypeId tid = TypeId("ns3::ArchHeader") .AddConstructor() // had to add this to get Socket::PrintTags to work .SetParent
(); // didn't do accessors how? return tid; } TypeId ArchHeader::GetInstanceTypeId(void) const { return GetTypeId(); } uint32_t ArchHeader::GetSerializedSize (void) const { return 2*sizeof(uint32_t) + str_value.size(); } void ArchHeader::Serialize (Buffer::Iterator i) const { if (debug) std::cout << "ArchHeader::Serialize() called" << std::endl; if (debug) std::cout << " int_value = " << int_value << std::endl; i.WriteU32 (int_value); uint32_t str_len = str_value.size(); if (debug) std::cout << " str_len = " << str_len << std::endl; i.WriteU32 (str_len); for (int j = 0; j < str_value.size(); j++) { if (debug) std::cout << " str_value[" << j << "] = " << str_value[j] << std::endl; i.WriteU8(str_value[j]); // NOTE: assumes 8bit chars. } } uint32_t ArchHeader::Deserialize (Buffer::Iterator i) { if (debug) std::cout << "ArchHeader::Deserialize() called" << std::endl; int_value = i.ReadU32 (); if (debug) std::cout << " int_value = " << int_value << std::endl; uint32_t str_len = i.ReadU32(); if (debug) std::cout << " str_len = " << str_len << std::endl; str_value.reserve(str_len); for (int j = 0; j < str_len; j++) { char v = i.ReadU8(); str_value.push_back(v); if (debug) std::cout << " str_value[" << j << "] = " << str_value[j] << std::endl; } if (debug) std::cout << "string is " << str_value << std::endl; return 2*sizeof(uint32_t) + str_value.size(); } void ArchHeader::SetIntValue(uint32_t v_) { int_value = v_; } uint32_t ArchHeader::GetIntValue(void) const { return int_value; } void ArchHeader::SetStrValue(const std::string &s) { str_value = s; } std::string ArchHeader::GetStrValue(void) const { return str_value; } void ArchHeader::Print (std::ostream &os) const { os << "(ArchHeader=" << str_value << ":" << int_value << ")"; } //------------- Application ------------------------ class TalkerApp : public Application { public: TalkerApp(); virtual ~TalkerApp (); void ConfRecv(Ptr, const Address,int); void ConfSend(Ptr, const Address,int); protected: virtual void DoDispose (void); private: virtual void StartApplication (void); virtual void StartApplicationRecv (void); virtual void StartApplicationSend (void); virtual void StopApplication (void); void HandleRead(Ptr); void SendPacket(std::string,char,int); void MarkPacket(Ptr,std::string,char); virtual void CloseConnection (Ptr socket); void ConnectionSucceeded(Ptr); void ConnectionFailed(Ptr); void ConnectionHalfClosed(Ptr); bool ConnectionRequested(Ptr, const Address &); void ConnectionCreated(Ptr, const Address &); void ConnectionCloseRequested(Ptr); bool verbose; Ptr m_socket; Ptr m_servsocket; Address m_local; Address m_remote; int i_am_listener; int recv_cnt; int m_send_size; int m_recv_size; }; TalkerApp::TalkerApp () : m_socket(0), m_servsocket(0), recv_cnt(0), verbose(1), m_send_size(0), m_recv_size(0) {} TalkerApp::~TalkerApp() {} void TalkerApp::DoDispose (void) { m_socket = 0; m_servsocket = 0; Application::DoDispose (); } void TalkerApp::CloseConnection (Ptr sock) { if (verbose) std::cout << "TalkerApp::CloseConnection(" << sock << "): " << (i_am_listener ? "Server" : "Client") << std::endl; sock->Close (); } void TalkerApp::ConnectionSucceeded(Ptr sock) { if (verbose) std::cout << "TalkerApp::ConnectionSucceeded(" << sock << "): " << (i_am_listener ? "Server" : "Client") << std::endl; } void TalkerApp::ConnectionFailed(Ptr sock) { if (verbose) std::cout << "TalkerApp::ConnectionFailed(" << sock << "): " << (i_am_listener ? "Server" : "Client") << std::endl; } void TalkerApp::ConnectionHalfClosed(Ptr sock) { if (verbose) std::cout << "TalkerApp::ConnectionHalfClosed(" << sock << "): " << (i_am_listener ? "Server" : "Client") << std::endl; } bool TalkerApp::ConnectionRequested(Ptr sock, const Address &addr) { if (verbose) std::cout << "TalkerApp::ConnectionRequested(" << sock << "," << addr << "): " << (i_am_listener ? "Server" : "Client") << std::endl; return(1); } void TalkerApp::ConnectionCreated(Ptr sock, const Address &addr) { if (verbose) std::cout << "TalkerApp::ConnectionCreated(" << sock << "," << addr << "): " << (i_am_listener ? "Server" : "Client") << std::endl; m_socket = sock; m_socket->SetRecvCallback(MakeCallback(&TalkerApp::HandleRead, this)); } void TalkerApp::ConnectionCloseRequested(Ptr sock) { if (verbose) std::cout << "TalkerApp::ConnectionCloseRequested(" << sock << "): " << (i_am_listener ? "Server" : "Client") << std::endl; } void TalkerApp::StartApplication() { if (verbose) std::cout << "TalkerApp::StartApplication() " << (i_am_listener ? "Server" : "Client") << std::endl; if (i_am_listener) StartApplicationRecv(); else StartApplicationSend(); } void TalkerApp::StartApplicationSend() { if (verbose) std::cout << "TalkerApp::StartApplicationSend() " << (i_am_listener ? "Server" : "Client") << std::endl; if (!m_socket) { m_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId()); m_socket->Bind (); } m_socket->Connect (m_remote); m_socket->SetConnectCallback ( MakeCallback(&TalkerApp::ConnectionSucceeded,this), MakeCallback(&TalkerApp::ConnectionFailed,this), MakeCallback(&TalkerApp::ConnectionHalfClosed,this) ); m_socket->SetRecvCallback(MakeCallback(&TalkerApp::HandleRead, this)); if (m_send_size) SendPacket(std::string("Hello"),'S',m_send_size); } void TalkerApp::StartApplicationRecv() { if (verbose) std::cout << "TalkerApp::StartApplicationRecv() " << (i_am_listener ? "Server" : "Client") << std::endl; if (!m_servsocket) { m_servsocket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId()); m_servsocket->Bind (m_local); m_servsocket->Listen (0); if (verbose) std::cout << " bound and listening on serversocket " << m_servsocket << std::endl; } m_servsocket->SetAcceptCallback ( MakeCallback(&TalkerApp::ConnectionRequested,this), MakeCallback(&TalkerApp::ConnectionCreated,this), MakeCallback(&TalkerApp::ConnectionCloseRequested,this) ); } void TalkerApp::ConfRecv(Ptr node, const Address addr,int size) { i_am_listener = 1; if (verbose) std::cout << "TalkerApp::ConfRecv(" << node << "," << addr << "," << size << ") " << (i_am_listener ? "Server" : "Client") << std::endl; m_local = addr; m_recv_size = size; node->AddApplication(this); } void TalkerApp::ConfSend(Ptr node, const Address addr,int size) { i_am_listener = 0; if (verbose) std::cout << "TalkerApp::ConfSend(" << node << "," << addr << "," << size << ") " << (i_am_listener ? "Server" : "Client") << std::endl; m_remote = addr; m_send_size = size; node->AddApplication(this); } void TalkerApp::MarkPacket(Ptr p,std::string label,char fill) { if (verbose) std::cout << "TalkerApp::MarkPacket(" << p << "," << label << "," << fill << ") " << (i_am_listener ? "Server" : "Client") << std::endl; p->Print(std::cout << "Before Marking|"); std::cout << std::endl; // lets try tags uint32_t size = p->GetSize(); Atag tag; tag.SetStrValue(label); tag.SetIntValue(size); p->AddTag(tag); p->Print(std::cout << "After Tag Marking|"); std::cout << std::endl; ArchHeader hdr; hdr.SetStrValue(label); hdr.SetIntValue(size); p->AddHeader(hdr); p->Print(std::cout << "After Header Marking|"); std::cout << std::endl; std::cout << std::endl; Atag tag_copy; p->FindFirstMatchingTag(tag_copy); tag_copy.Print(std::cout << "TalkerApp::MarkPacket Tag::Print| "); p->PrintTags(std::cout << "TalkerApp::MarkPacket Packet::PrintTags| "); std::cout << std::endl; } void TalkerApp::SendPacket(std::string label,char fill,int payloadsize) { int size = payloadsize; if (verbose) std::cout << "TalkerApp::SendPacket(" << label << "," << fill << "," << payloadsize << ") " << (i_am_listener ? "Server" : "Client") << std::endl; Ptr p = Create(payloadsize); MarkPacket(p,label,fill); if (verbose) std::cout << " sending on socket " << m_socket << std::endl; m_socket->Send(p); } void TalkerApp::StopApplication() { if (m_socket) m_socket->SetRecvCallback (MakeNullCallback > ()); } void TalkerApp::HandleRead(Ptr socket) { if (verbose) std::cout << "TalkerApp::HandleRead(" << socket << "): " << (i_am_listener ? "Server" : "Client") << std::endl; if (i_am_listener && recv_cnt++ == 0 && m_recv_size) { SendPacket(std::string("BackAtYou"),'R', m_recv_size); } Ptr packet; while (packet = socket->Recv()){ SocketRxAddressTag rx_addr_tag; bool found; found = packet->FindFirstMatchingTag (rx_addr_tag); NS_ASSERT (found); Address from = rx_addr_tag.GetAddress (); // XXX packet->RemoveTag (tag); if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from); std::cout << std::setw(4) << packet->GetSize() << " bytes from " << address.GetIpv4() << " [" << address << "] "; packet->Print(std::cout << " "); packet->PrintTags(std::cout << "|"); std::cout << std::endl; } else { std::cout << "not a match in HandleRead" << std::endl; } } } int main (int argc, char *argv[]) { int send_size = 600; int recv_size = 700; if (argc == 3) { send_size = atoi(argv[1]); recv_size = atoi(argv[2]); } RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8); Packet::EnableMetadata(); NodeContainer c0; c0.Create (2); // We create the channels first without any IP addressing information PointToPointHelper p2p; p2p.SetDeviceParameter("DataRate",DataRateValue(DataRate(10000000))); p2p.SetChannelParameter ("Delay",TimeValue(MilliSeconds(10))); NetDeviceContainer dev0 = p2p.Install(c0); // add ip/tcp stack to nodes. InternetStackHelper internet; internet.Install (c0); // Later, we add IP addresses. Ipv4AddressHelper ipv4; ipv4.SetBase ("10.1.0.0", "255.255.255.0"); Ipv4InterfaceContainer ifaces = ipv4.Assign (dev0); // Configure the apps. uint16_t servPort = 32; TalkerApp source; source.ConfSend(c0.Get(0), InetSocketAddress (ifaces.GetAddress (1), servPort),send_size); source.Start(Seconds(0.0)); TalkerApp sink; sink.ConfRecv(c0.Get(1), InetSocketAddress (Ipv4Address::GetAny(), servPort), recv_size); sink.Start (Seconds (0.0)); //Simulator::Stop (Seconds(10)); std::ofstream ascii; ascii.open("tcp-2way.tr"); PointToPointHelper::EnableAsciiAll(ascii); PointToPointHelper::EnablePcapAll("tcp-2way"); Simulator::Run (); Simulator::Destroy (); }