< Previous by Date Date Index Next by Date >
  Thread Index Next in Thread >

[reSIProcate] MessageDecorator bug?


Hi,
I'm testing DUM using Resiprocate release 1.4 (SVN head) and have
noticed a strange behaviour about MessageDecorator invocation while
sending a SIP message.

To reproduce the issue I changed the sample application
basicRregister.cxx file  (in "dum/test/directory") with some
modifications: I added my class SipMessageDecorator, invoked
setOutboundDecorator(), added logs and removed unregistration so that
the REGISTER message is always sent.

I set my MessageDecorator class in the main with
setOutboundDecorator() method, in this way:
SharedPtr<SipMessageDecorator> messageDecorator(new SipMessageDecorator());
clientDum.getMasterProfile()->setOutboundDecorator(messageDecorator);

After sending the first REGISTER message, the method decorateMessage()
in MessageDecorator class is called once, but the second time it is
called consecutively twice with the same message, at third REGISTER
three times (always same message) and so on.

I noticed that in DialogUsageManager the send() method adds a
MessageDecorator clone to mOutboundDecorators and the
SipMessage::callOutboundDecorator() method  calls decorateMessage()
for each item in vector mOutboundDecorators, but this vector always
grows.

I attached to this mail the changed sample application that I tested
using repro and the produced log file.

Is there a bug or my mistake?

Thank you in advance.
Best regards

Andrea Chiappori
#include "resip/stack/SipStack.hxx"
#include "resip/dum/ClientAuthManager.hxx"
#include "resip/dum/ClientRegistration.hxx"
#include "resip/dum/DialogUsageManager.hxx"
#include "resip/dum/MasterProfile.hxx"
#include "resip/dum/RegistrationHandler.hxx"
#include "rutil/Log.hxx"
#include "rutil/Logger.hxx"
#include "rutil/Subsystem.hxx"
#include "resip/dum/KeepAliveManager.hxx"

#ifdef WIN32
#include "resip/stack/WinSecurity.hxx"
#endif

#define RESIPROCATE_SUBSYSTEM Subsystem::TEST

using namespace resip;
using namespace std;

class ClientHandler : public ClientRegistrationHandler
{
   public:
      ClientHandler() : done(false) {}

      virtual void onSuccess(ClientRegistrationHandle h, const SipMessage& 
response)
      {
         InfoLog( << "ClientHandler::onSuccess: " << endl );
                        resipCerr << "ClientHandler::onSuccess" << endl;        

                        //removed to test registration continuously
/*
         resipCerr << "Pausing before unregister" << endl;
         
#ifdef WIN32
         Sleep(2000);
#else
         sleep(5);
#endif
         h->removeAll();                
*/  
                }

      virtual void onRemoved(ClientRegistrationHandle, const SipMessage& 
response)
      {
         InfoLog ( << "ClientHandler::onRemoved ");
                        resipCerr << "ClientHandler::onRemoved" << endl;        
         done = true;
      }

      virtual void onFailure(ClientRegistrationHandle, const SipMessage& 
response)
      {
         InfoLog ( << "ClientHandler::onFailure: " << response );
                        resipCerr << "ClientHandler::onFailure" << endl;        
      }

      virtual int onRequestRetry(ClientRegistrationHandle, int retrySeconds, 
const SipMessage& response)
      {
         InfoLog ( << "ClientHandler:onRequestRetry");
                        resipCerr << "ClientHandler::onRequestRetry" << endl;
         return -1;
      }
      
      bool done;
};

//////////////////////////////////////////////////////////////////////////////

class SipMessageDecorator : public MessageDecorator
{
        
public:
        explicit SipMessageDecorator(SipMessageDecorator* messageDecorator){}
        explicit SipMessageDecorator(){}                

        virtual ~SipMessageDecorator(){}

         
        // MessageDecorator
        virtual void decorateMessage(SipMessage& msg, 
                                                                                
  const Tuple& source,
                                                                                
  const Tuple& destination) 
        {
                InfoLog ( << "SipMessageDecorator::decorateMessage" << endl);
                resipCerr << "SipMessageDecorator::decorateMessage" << endl;


                DebugLog ( << "SIP message" << Data::from(msg).c_str());
                DebugLog ( <<"source" << Data::from(source).c_str());
                DebugLog( << "destination" << Data::from(destination).c_str());
        }

        virtual void rollbackMessage(SipMessage& msg){};
        virtual MessageDecorator* clone() const{ 
                SipMessageDecorator* messageDecorator =
                        const_cast<SipMessageDecorator*>(this);
                return new SipMessageDecorator(messageDecorator);
        }
}; // class SipMessageDecorator


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

int 
main (int argc, char** argv)
{

   if ( argc < 3 ) {
      resipCout << "usage: " << argv[0] << " sip:user passwd\n";
      return 0;
   }

   Log::initialize(Log::Cout, Log::Stack, argv[0]);

   NameAddr userAor(argv[1]);
   Data passwd(argv[2]);
        
        userAor.displayName() = userAor.uri().user();


#ifdef USE_SSL
#ifdef WIN32
   Security* security = new WinSecurity;
#else
   Security* security = new Security;
#endif
   SipStack stack(security);
#else
   SipStack stack;
#endif

   DialogUsageManager clientDum(stack);                                         
                        
   SharedPtr<MasterProfile> profile(new MasterProfile);         
   auto_ptr<ClientAuthManager> clientAuth(new ClientAuthManager);   
   ClientHandler clientHandler;

   clientDum.addTransport(UDP, 10000 + rand()&0x7fff, V4);
   // clientDum.addTransport(UDP, 10000 + rand()&0x7fff, V6);
   clientDum.addTransport(TCP, 10000 + rand()&0x7fff, V4);
   // clientDum.addTransport(TCP, 10000 + rand()&0x7fff, V6);
#ifdef USE_SSL
   clientDum.addTransport(TLS, 10000 + rand()&0x7fff, V4);
   // clientDum.addTransport(TLS, 10000 + rand()&0x7fff, V6);
#endif
   clientDum.setMasterProfile(profile);
   clientDum.setClientRegistrationHandler(&clientHandler);
   clientDum.setClientAuthManager(clientAuth);
   clientDum.getMasterProfile()->setDefaultRegistrationTime(70);

   // keep alive test.
   auto_ptr<KeepAliveManager> keepAlive(new KeepAliveManager);
   clientDum.setKeepAliveManager(keepAlive);

   clientDum.getMasterProfile()->setDefaultFrom(userAor);
   profile->setDigestCredential(userAor.uri().host(),
                                     userAor.uri().user(),
                                     passwd);

        //add call to setOutboundDecorator 
        SharedPtr<SipMessageDecorator> messageDecorator(new 
SipMessageDecorator());
        clientDum.getMasterProfile()->setOutboundDecorator(messageDecorator);

   SharedPtr<SipMessage> regMessage = clientDum.makeRegistration(userAor);
   NameAddr contact;

   clientDum.send( regMessage );        

   int n = 0;
   while ( !clientHandler.done )
   {
      FdSet fdset;

      stack.buildFdSet(fdset);
      int err = fdset.selectMilliSeconds(100);
      assert ( err != -1 );

      stack.process(fdset);
      while(clientDum.process());

                //removed to test registration continuously
//      if (n == 1000) 
//                      clientHandler.done = true;

      if (!(n++ % 10)) 
                        cerr << "|/-\\"[(n/10)%4] << '\b';
   }   
   return 0;
}

/* ====================================================================
 * The Vovida Software License, Version 1.0 
 * 
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
 *    and "Vovida Open Communication Application Library (VOCAL)" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact vocal@xxxxxxxxxxx
 *
 * 4. Products derived from this software may not be called "VOCAL", nor
 *    may "VOCAL" appear in their name, without prior written
 *    permission of Vovida Networks, Inc.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 * 
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by Vovida
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
 * Inc.  For more information on Vovida Networks, Inc., please see
 * <http://www.vovida.org/>.
 *
 */

Attachment: test.log
Description: Binary data