src/contrib/net-anim/animation-interface.cc
changeset 5776 aae948449722
parent 5775 86ff2e00d4ea
child 5777 a7ca957db043
child 5812 bb8a3a22d015
equal deleted inserted replaced
5775:86ff2e00d4ea 5776:aae948449722
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * This program is free software; you can redistribute it and/or modify
       
     4  * it under the terms of the GNU General Public License version 2 as
       
     5  * published by the Free Software Foundation;
       
     6  *
       
     7  * This program is distributed in the hope that it will be useful,
       
     8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
     9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    10  * GNU General Public License for more details.
       
    11  *
       
    12  * You should have received a copy of the GNU General Public License
       
    13  * along with this program; if not, write to the Free Software
       
    14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    15  *
       
    16  * Author: George F. Riley<riley@ece.gatech.edu>
       
    17  */
       
    18 
       
    19 // Interface between ns3 and the network animator
       
    20 
       
    21 #include <stdio.h>
       
    22 #include <sstream>
       
    23 
       
    24 #include "ns3/net-anim-config.h"
       
    25 
       
    26 // Socket related includes
       
    27 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
       
    28 # include <sys/socket.h>
       
    29 # include <netinet/in.h>
       
    30 #else
       
    31 #include <fcntl.h>
       
    32 #endif
       
    33 
       
    34 // ns3 includes
       
    35 #include "ns3/animation-interface.h"
       
    36 #include "ns3/channel.h"
       
    37 #include "ns3/config.h"
       
    38 #include "ns3/node.h"
       
    39 #include "ns3/node-location.h"
       
    40 #include "ns3/packet.h"
       
    41 #include "ns3/simulator.h"
       
    42 
       
    43 using namespace std;
       
    44 
       
    45 NS_LOG_COMPONENT_DEFINE ("AnimationInterface");
       
    46 
       
    47 namespace ns3 {
       
    48 
       
    49 AnimationInterface::AnimationInterface ()
       
    50   : m_fHandle (STDOUT_FILENO), m_model (0)
       
    51 {
       
    52 }
       
    53 
       
    54 bool AnimationInterface::SetOutputFile (const std::string& fn)
       
    55 {
       
    56   FILE* f = fopen (fn.c_str (), "w");
       
    57   if (!f)
       
    58     {
       
    59       return false; // Can't open
       
    60     }
       
    61   m_fHandle = fileno (f); // Set the file handle
       
    62   return true;
       
    63 }
       
    64 
       
    65 bool AnimationInterface::SetServerPort (uint16_t port)
       
    66 {
       
    67 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
       
    68   int s = socket (AF_INET, SOCK_STREAM, 0);
       
    69   struct sockaddr_in addr;
       
    70   addr.sin_family = AF_INET;
       
    71   addr.sin_port = htons (port);
       
    72   addr.sin_addr.s_addr = htonl (INADDR_ANY);
       
    73   if (bind (s, (struct sockaddr*)&addr, sizeof (addr)) < 0)
       
    74     {
       
    75       NS_LOG_WARN ("Can't bind to port " << port << ", exiting.");
       
    76       return false;
       
    77     }
       
    78   listen (s, 1);
       
    79   NS_LOG_INFO ("Waiting for animator connection");
       
    80   // Now wait for the animator to connect in
       
    81   m_fHandle = accept (s, 0, 0);
       
    82   NS_LOG_INFO ("Got animator connection from remote");
       
    83   // set the linger socket option
       
    84   int t = 1;
       
    85   setsockopt (s, SOL_SOCKET, SO_LINGER, &t, sizeof(t));
       
    86   return true;
       
    87 #endif
       
    88   return false;//never reached unless the above is disabled
       
    89 }
       
    90 
       
    91 bool AnimationInterface::SetInternalAnimation ()
       
    92 {
       
    93   return false; // Not implemented yet
       
    94 }
       
    95 
       
    96 void AnimationInterface::StartAnimation ()
       
    97 {
       
    98   // Dump the topology
       
    99   for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
       
   100     {
       
   101       Ptr<Node> n = *i;
       
   102       Ptr<NodeLocation> loc = n->GetObject<NodeLocation> ();
       
   103       if (loc)
       
   104         {
       
   105           // Location exists, dump it
       
   106           Vector v = loc->GetLocation ();
       
   107           ostringstream oss;
       
   108           oss << "0.0 N " << n->GetId () 
       
   109                << " " << v.x << " " << v.y << endl;
       
   110           WriteN (m_fHandle, oss.str ().c_str (), oss.str ().length ());
       
   111         }
       
   112     }
       
   113   // Now dump the p2p links
       
   114   for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End(); ++i)
       
   115     {
       
   116       Ptr<Node> n = *i;
       
   117       uint32_t n1Id = n->GetId ();
       
   118       uint32_t nDev = n->GetNDevices ();  // Number of devices
       
   119       for (uint32_t i = 0; i < nDev; ++i)
       
   120         {
       
   121           Ptr<NetDevice> dev = n->GetDevice (i);
       
   122           Ptr<Channel>   ch = dev->GetChannel ();
       
   123           if (!ch) 
       
   124             {
       
   125               continue; // No channel, can't be p2p device
       
   126             }
       
   127           string channelType = ch->GetInstanceTypeId ().GetName ();
       
   128           if (channelType == string ("ns3::PointToPointChannel"))
       
   129             { // Since these are duplex links, we only need to dump
       
   130               // if srcid < dstid
       
   131               uint32_t nChDev = ch->GetNDevices ();
       
   132               for (uint32_t j = 0; j < nChDev; ++j)
       
   133                 {
       
   134                   Ptr<NetDevice> chDev = ch->GetDevice (j);
       
   135                   uint32_t n2Id = chDev->GetNode ()->GetId ();
       
   136                   if (n1Id < n2Id)
       
   137                     { // ouptut the p2p link
       
   138                       ostringstream oss;
       
   139                       oss << "0.0 L "  << n1Id << " " << n2Id << endl;
       
   140                       WriteN (m_fHandle, oss.str ().c_str (),
       
   141                              oss.str ().length ());
       
   142                     }
       
   143                 }
       
   144             }
       
   145           else
       
   146             {
       
   147               NS_FATAL_ERROR ("Net animation currently only supports point-to-point links.");
       
   148             }
       
   149         }
       
   150     }
       
   151   
       
   152   // Connect the callback for packet tx events
       
   153   Config::Connect ("/ChannelList/*/TxRxPointToPoint",
       
   154                    MakeCallback (&AnimationInterface::DevTxTrace, this));
       
   155 }
       
   156 
       
   157 void AnimationInterface::StopAnimation ()
       
   158 {
       
   159   if (m_fHandle > 0) 
       
   160     {
       
   161       close (m_fHandle);
       
   162     }
       
   163 }
       
   164 
       
   165 
       
   166 // Private methods
       
   167 int AnimationInterface::WriteN (int h, const char* data, uint32_t count)
       
   168 { // Write count bytes to h from data
       
   169   uint32_t    nLeft   = count;
       
   170   const char* p       = data;
       
   171   uint32_t    written = 0;
       
   172 
       
   173   while (nLeft)
       
   174     {
       
   175       int n = write (h, p, nLeft);
       
   176       if (n <= 0) 
       
   177         {
       
   178           return written;
       
   179         }
       
   180       written += n;
       
   181       nLeft -= n;
       
   182       p += n;
       
   183     }
       
   184   return written;
       
   185 }
       
   186   
       
   187 void AnimationInterface::DevTxTrace (std::string context, Ptr<const Packet> p,
       
   188                                      Ptr<NetDevice> tx, Ptr<NetDevice> rx,
       
   189                                      Time txTime, Time rxTime)
       
   190 {
       
   191   Time now = Simulator::Now ();
       
   192   ostringstream oss;
       
   193   oss << now.GetSeconds() << " P "
       
   194       << tx->GetNode ()->GetId () << " "
       
   195       << rx->GetNode ()->GetId () << " "
       
   196       << (now + txTime).GetSeconds () << " " // last bit tx time
       
   197       << (now + rxTime - txTime).GetSeconds() << " "  // first bit rx time
       
   198       << (now + rxTime).GetSeconds () << endl;         // last bit rx time
       
   199   WriteN (m_fHandle, oss.str ().c_str (), oss.str ().length ());
       
   200 }
       
   201 
       
   202 } // namespace ns3