reSIProcate/stack  9694
Defines | Functions
testTcp.cxx File Reference
#include <signal.h>
#include <iostream>
#include "resip/stack/TcpTransport.hxx"
#include "resip/stack/Helper.hxx"
#include "resip/stack/PlainContents.hxx"
#include "resip/stack/SipMessage.hxx"
#include "resip/stack/Uri.hxx"
#include "resip/stack/ExtensionHeader.hxx"
#include "rutil/Data.hxx"
#include "rutil/DnsUtil.hxx"
#include "rutil/Logger.hxx"
#include "rutil/Random.hxx"
#include "rutil/DataStream.hxx"
Include dependency graph for testTcp.cxx:

Go to the source code of this file.

Defines

#define RESIPROCATE_SUBSYSTEM   Subsystem::SIP

Functions

int main (int argc, char *argv[])

Define Documentation

#define RESIPROCATE_SUBSYSTEM   Subsystem::SIP

Definition at line 31 of file testTcp.cxx.


Function Documentation

int main ( int  argc,
char *  argv[] 
)

Definition at line 34 of file testTcp.cxx.

References resip::TcpBaseTransport::buildFdSet(), resip::SipMessage::checkContentLength, context, resip::Log::Cout, dest, resip::Data::Empty, resip::SipMessage::encode(), resip::SipMessage::encodeSipFrag(), resip::Data::from(), resip::Fifo< Msg >::getNext(), resip::Random::getRandom(), resip::Timer::getTimeMs(), resip::SipMessage::header(), resip::Uri::host(), resip::DnsUtil::inet_pton(), resip::Log::Info, InfoLog, resip::Log::initialize(), resip::initNetwork(), resip::Helper::makeInvite(), resip::Transport::makeSendData(), resip::AbstractFifo< T >::messageAvailable(), resip::ParserCategory::param(), resip::Uri::port(), resip::Transport::port(), resip::TcpBaseTransport::process(), received, resip::Data::replace(), resip::Uri::scheme(), resip::FdSet::selectMilliSeconds(), resip::InternalTransport::send(), resip::SipMessage::setContents(), resip::TCP, resip::toData(), resip::TcpTransport::transport(), type, resip::RequestLine::uri(), resip::NameAddr::uri(), resip::Uri::user(), and resip::V4.

{
#ifndef _WIN32
   if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
   {
      cerr << "Couldn't install signal handler for SIGPIPE" << endl;
      exit(-1);
   }
#endif

#ifdef WIN32
   initNetwork();
#endif

   char* logType = 0;
   const char* logLevel = "WARNING";
   int runs = 100;
   int window = 10;
   int seltime = 100;

#if defined(HAVE_POPT_H)
   struct poptOption table[] = {
      {"log-type",    'l', POPT_ARG_STRING, &logType,   0, "where to send logging messages", "syslog|cerr|cout"},
      {"log-level",   'v', POPT_ARG_STRING, &logLevel,  0, "specify the default log level", "DEBUG|INFO|WARNING|ALERT"},
      {"num-runs",    'r', POPT_ARG_INT,    &runs,      0, "number of calls in test", 0},
      {"window-size", 'w', POPT_ARG_INT,    &window,    0, "number of registrations in test", 0},
      {"select-time", 's', POPT_ARG_INT,    &seltime,   0, "number of runs in test", 0},
      POPT_AUTOHELP
      { NULL, 0, 0, NULL, 0 }
   };
   
   poptContext context = poptGetContext(NULL, argc, const_cast<const char**>(argv), table, 0);
   poptGetNextOpt(context);
   poptFreeContext(context);
#endif

#ifdef WIN32
   Log::initialize(Log::Cout, Log::Info, "testTcp");   
#else
   Log::initialize(logType, logLevel, argv[0]);
#endif
   
   cout << "Performing " << runs << " runs." << endl;
   
   Fifo<TransactionMessage> txFifo;
   TcpTransport* sender = new TcpTransport(txFifo, 5070, V4, Data::Empty);

   Fifo<TransactionMessage> rxFifo;
   TcpTransport* receiver = new TcpTransport(rxFifo, 5080, V4, Data::Empty);
   
   NameAddr target;
   target.uri().scheme() = "sip";
   target.uri().user() = "fluffy";
   target.uri().host() = "localhost";
   target.uri().port() = 5080;
   target.uri().param(p_transport) = "tcp";
   
   NameAddr from = target;
   from.uri().port() = 5070;

   InfoLog (<< "Creating messages");
   
   list<SipMessage*> messages;
   {
      UInt64 startTime = Timer::getTimeMs();
      for (int i=0; i<runs; i++)
      {
         SipMessage* m = Helper::makeInvite( target, from, from);      
         m->header(h_Vias).front().transport() = Tuple::toData(sender->transport());
         m->header(h_Vias).front().sentHost() = "localhost";
         m->header(h_Vias).front().sentPort() = sender->port();
         int contentLength=resip::Random::getRandom()%65535;
         std::string body(contentLength,'0');
         std::auto_ptr<Contents> contents(new PlainContents(Data(body.data(), body.size())));
         m->setContents(contents);
         int headerLength=resip::Random::getRandom()%1024;
         std::string bigHeader(headerLength,'h');
         m->header(h_Subject).value()=Data(bigHeader.data(), bigHeader.size());
         messages.push_back(m);
      }

      UInt64 elapsed = Timer::getTimeMs() - startTime;
      cout << runs << " calls performed in " << elapsed << " ms, a rate of " 
           << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;
      
      InfoLog (<< "Messages created");
   }
   
   //delete receiver;
   //receiver=0;
   
   in_addr in;
   DnsUtil::inet_pton("127.0.0.1", in);
   Tuple dest(in, target.uri().port(), TCP);
   InfoLog (<< "Sending to " << dest);
   
   UInt64 startTime = Timer::getTimeMs();

   int tid=1;
   int outstanding=0;

   while (!messages.empty())
   {
      // load up the send window
      while (outstanding < window)
      {
         Data encoded;
         {
            DataStream strm(encoded);
            SipMessage* next = messages.front();
            messages.pop_front();
            next->encode(strm);
            outstanding++;
            delete next;
         }
         std::auto_ptr<SendData> toSend(sender->makeSendData(dest, encoded, Data(tid++), Data::Empty));
         sender->send(toSend);
      }

      FdSet fdset; 
      if (receiver) receiver->buildFdSet(fdset);
      sender->buildFdSet(fdset);

      fdset.selectMilliSeconds(seltime); 
      
      if (receiver) receiver->process(fdset);
      sender->process(fdset);
      
      Message* msg;
      if (rxFifo.messageAvailable())
      {
         msg = rxFifo.getNext();
         SipMessage* received = dynamic_cast<SipMessage*>(msg);
         if (received)
         {
            //DebugLog (<< "got: " << received->brief());
            outstanding--;
         
            assert (received->header(h_RequestLine).uri().host() == "localhost");
            assert (received->header(h_To).uri().host() == "localhost");
            assert (received->header(h_From).uri().host() == "localhost");
            assert (!received->header(h_Vias).begin()->sentHost().empty());
            assert (received->header(h_Contacts).begin()->uri().host() == "localhost");
            assert (!received->header(h_CallId).value().empty());
         }
         delete msg;
      }
   }

   while (outstanding>0)
   {
      FdSet fdset; 
      if (receiver) receiver->buildFdSet(fdset);
      sender->buildFdSet(fdset);

      fdset.selectMilliSeconds(seltime); 
      
      if (receiver) receiver->process(fdset);
      sender->process(fdset);

      while (rxFifo.messageAvailable())
      {
         Message* msg = rxFifo.getNext();
         SipMessage* received = dynamic_cast<SipMessage*>(msg);
         if (received)
         {
            //DebugLog (<< "got: " << received->brief());
            outstanding--;
         
            assert (received->header(h_RequestLine).uri().host() == "localhost");
            assert (received->header(h_To).uri().host() == "localhost");
            assert (received->header(h_From).uri().host() == "localhost");
            assert (!received->header(h_Vias).begin()->sentHost().empty());
            assert (received->header(h_Contacts).begin()->uri().host() == "localhost");
            assert (!received->header(h_CallId).value().empty());
         }
         delete msg;
      }
   }

   UInt64 elapsed = Timer::getTimeMs() - startTime;
   cout << runs << " calls peformed in " << elapsed << " ms, a rate of " 
        << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;

   SipMessage::checkContentLength=false;
   list<SipMessage*> garbage;
   {
      UInt64 startTime = Timer::getTimeMs();
      for (int i=0; i<runs; i++)
      {
         SipMessage* m = Helper::makeInvite( target, from, from);      
         m->header(h_Vias).front().transport() = Tuple::toData(sender->transport());
         m->header(h_Vias).front().sentHost() = "localhost";
         m->header(h_Vias).front().sentPort() = sender->port();
          
         garbage.push_back(m);
      }

      UInt64 elapsed = Timer::getTimeMs() - startTime;
      cout << runs << " calls performed in " << elapsed << " ms, a rate of " 
           << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;
      
      InfoLog (<< "Messages created");
   }

   int type=0;
   Data badContentLength1("-1");
   Data badContentLength2("999999999999999999999999999999");
   std::string hugeString(4096,'h');
   ExtensionHeader h_huge(Data::from(hugeString));

   while (!garbage.empty())
   {
      Data encoded;
            
      switch(type%4)
      {
         case 0:
         case 1:
         {
            // .bwc. Send one at a time for maximum potential damage.
            {
               DataStream strm(encoded);
               SipMessage* next = garbage.front();
               garbage.pop_front();
               // .bwc. encodeSipFrag doesn't encode Content-Length if there is no
               // body; allowing us to add a bad one without conflicting.
               next->encodeSipFrag(strm);
               outstanding++;
               delete next;
            }

            encoded.replace("\r\n\r\n","\r\nContent-Length: "+( type ? badContentLength1 : badContentLength2)+"\r\n\r\n");
         }
         break;
         case 2:
         {
            DataStream strm(encoded);
            SipMessage* next = garbage.front();
            garbage.pop_front();
            next->header(h_Subject).value()=Data(hugeString.data(), hugeString.size());
            next->encode(strm);
            delete next;
         }
         break;
         case 3:
         {
            DataStream strm(encoded);
            SipMessage* next = garbage.front();
            garbage.pop_front();
            next->header(h_huge).push_front(StringCategory("foo"));
            next->encode(strm);
            delete next;
         }
         break;
      }

      ++type;
      std::auto_ptr<SendData> toSend(sender->makeSendData(dest, encoded, Data(tid++), Data::Empty));
      sender->send(toSend);

      FdSet fdset; 
      if (receiver) receiver->buildFdSet(fdset);
      sender->buildFdSet(fdset);

      fdset.selectMilliSeconds(seltime); 
      
      try
      {
         if (receiver) receiver->process(fdset);
      }
      catch(std::exception& e)
      {
         // .bwc. Do nothing substantive, since the stack thread doesn't
      }
      sender->process(fdset);
      
      Message* msg;
      while (rxFifo.messageAvailable())
      {
         msg = rxFifo.getNext();
         SipMessage* received = dynamic_cast<SipMessage*>(msg);
         // .bwc. These are all unrecoverable garbage, we should not get
         // any sip traffic on this fifo.
         assert(!received);
         delete msg;
      }
   }

   return 0;
}

Here is the call graph for this function: