⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tuim.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif

/* TODO list for this file ....
   handle 302 in message
   handle 302 in subscribe

   sort out how contact is formed 
   keep track of ourstanding message dialogs 
   add a publish sending dialogs 
   send options to register, see if do publish, if so use 

   suppport loading destination certificates from server 
*/

#include <cassert>
#include <memory>

#include "resip/stack/SipStack.hxx"
#include "resip/stack/DeprecatedDialog.hxx"
#include "resip/stack/SipMessage.hxx"
#include "resip/stack/TuIM.hxx"
#include "resip/stack/Contents.hxx"
#include "resip/stack/ParserCategories.hxx"
#include "resip/stack/PlainContents.hxx"
#include "resip/stack/CpimContents.hxx"
#include "resip/stack/Pkcs7Contents.hxx"
#include "resip/stack/MultipartSignedContents.hxx"
#include "resip/stack/MultipartMixedContents.hxx"
#include "resip/stack/OctetContents.hxx"
#include "resip/stack/Security.hxx"
#include "resip/stack/Helper.hxx"
#include "resip/stack/Pidf.hxx"
#include "resip/stack/SipFrag.hxx"
#include "rutil/Data.hxx"
#include "rutil/Logger.hxx"
#include "rutil/Random.hxx"
#include "rutil/Socket.hxx"
#include "rutil/WinLeakCheck.hxx"

#define RESIPROCATE_SUBSYSTEM Subsystem::SIP

using namespace resip;
using namespace std;

static int IMMethodList[] = { (int) REGISTER, 
                              (int) MESSAGE, 
	                      (int) SUBSCRIBE, 
                              (int) NOTIFY };
const int IMMethodListSize = sizeof(IMMethodList) / sizeof(*IMMethodList);


TuIM::Callback::~Callback()
{
}


TuIM::TuIM(SipStack* stack, 
           const Uri& aor, 
           const Uri& contact,
           Callback* callback,
           const int registrationTimeSeconds,
           const int subscriptionTimeSeconds)
   : mCallback(callback),
     mStack(stack),
     mAor(aor),
     mContact(contact),
     mPidf( new Pidf ),
     mRegistrationDialog(NameAddr(contact)),
     mNextTimeToRegister(0),
     mRegistrationPassword( Data::Empty ),
     mLastAuthCSeq(0),
     mRegistrationTimeSeconds(registrationTimeSeconds),
     mSubscriptionTimeSeconds(subscriptionTimeSeconds),
     mDefaultProtocol( UNKNOWN_TRANSPORT )
{
   assert( mStack );
   assert(mCallback);
   assert(mPidf);
   
   mPidf->setSimpleId( Random::getRandomHex(4) );  
   mPidf->setEntity(mAor);  
   mPidf->setSimpleStatus( true, Data::Empty, mContact.getAor() );
}


bool
TuIM::haveCerts( bool sign, const Data& encryptFor )
{
/*   assert(0); */

#if defined( USE_SSL )
   Security* sec = mStack->getSecurity();
   assert(sec);
   
   if ( sign )
   {    
      if ( !sec->hasUserPrivateKey(mAor.getAor()) )
      {
         return false;
      }
   } 
   if ( !encryptFor.empty() )
   {
      if ( !sec->hasUserCert( encryptFor ) )
      {
         return false;
      }
   }
#else
   if ( (!encryptFor.empty()) || (sign) )
   {
      return false;
   }
#endif
   return true;
}


void 
TuIM::sendPage(const Data& text, const Uri& dest, 
               const bool sign, const Data& encryptFor)
{
   if ( text.empty() )
   {
      DebugLog( << "tried to send blank message - dropped " );
      return;
   }
   DebugLog( << "send to <" << dest << ">" << "\n" << text );

   NameAddr target;
   target.uri() = dest;
   
   NameAddr from;
   from.uri() = mAor;

   NameAddr contact;
   contact.uri() = mContact;

   DeprecatedDialog* dialog = new DeprecatedDialog( NameAddr(mContact) );
 
   auto_ptr<SipMessage> msg( dialog->makeInitialMessage(NameAddr(target),NameAddr(from)) );
 
   Page page;
   page.text = text;
   page.uri = dest;
   page.sign = sign;
   page.encryptFor = encryptFor;
   page.dialog = dialog;
   
   mPages.push_back(page);
   
   Contents* body = ( new PlainContents(text) );
#if 1
   msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
#endif

#if defined( USE_SSL )
   if ( !encryptFor.empty() )
   {
      Security* sec = mStack->getSecurity();
      assert(sec);
      
      Contents* old = body;
      old->header(h_ContentTransferEncoding) = msg->header(h_ContentTransferEncoding);
      body = sec->encrypt( old, encryptFor );
      delete old;

      if ( !body )
      {
         mCallback->sendPageFailed( dest, -2 );
         return;
      }

#if 0      
      msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
#endif
   }

   if ( sign )
   {
      Security* sec = mStack->getSecurity();
      assert(sec);
    
      Contents* old = body;
      old->header(h_ContentTransferEncoding) = msg->header(h_ContentTransferEncoding);
      body = sec->sign( mAor.getAor(), old );
      delete old;

      if ( !body )
      {
         mCallback->sendPageFailed( dest, -1 );
         return;
      }

#if 0
      msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
#endif
   }
#endif

   msg->setContents(body);

   if (1)       // Compute the identity header.
   {
      //Security* sec = mStack->getSecurity();
      //assert(sec);
      
      DateCategory now;
      msg->header(h_Date) = now;
      
      //Data token = msg->getCanonicalIdentityString();
      //Data res = sec->computeIdentity( token );

      msg->header(h_Identity).value() = Data::Empty;
   }
   
   setOutbound( *msg );
   //ErrLog( "About to send " << *msg );
   
   mStack->send( *msg );

   delete body;
}


void
TuIM::processRequest(SipMessage* msg)
{
   if ( msg->header(h_RequestLine).getMethod() == MESSAGE )
   {
      processMessageRequest(msg);
      return;
   }
   if ( msg->header(h_RequestLine).getMethod() == SUBSCRIBE )
   {
      processSubscribeRequest(msg);
      return;
   }
   if ( msg->header(h_RequestLine).getMethod() == REGISTER )
   {
      processRegisterRequest(msg);
      return;
   }
   if ( msg->header(h_RequestLine).getMethod() == NOTIFY )
   {
      processNotifyRequest(msg);
      return;
   }

   InfoLog(<< "Don't support this METHOD, send 405" );
   
   SipMessage * resp = Helper::make405( *msg, IMMethodList, IMMethodListSize ); 
   mStack->send(*resp); 
   delete resp;
}


void 
TuIM::processSipFrag(SipMessage* msg)
{
   Contents* contents = msg->getContents();
   if ( !contents )
   {
      InfoLog(<< "Received message with no contents" );
      return;
   }

   InfoLog(<< "Received message with body contents" );

   assert( contents );
   Mime mime = contents->getType();
   DebugLog ( << "got body of type  " << mime.type() << "/" << mime.subType() );

   Data signedBy;

#if defined( USE_SSL )
   SignatureStatus sigStat = SignatureNone;
   MultipartSignedContents* mBody = dynamic_cast<MultipartSignedContents*>(contents);
   if ( mBody )
   {
      Security* sec = mStack->getSecurity();
      assert(sec);
      
      contents = sec->checkSignature( mBody, &signedBy, &sigStat );
      
      if ( !contents )
      { 
         InfoLog( << "Some problem decoding multipart/signed message");
         return;
      } 

      InfoLog( << "Signed by " << signedBy << " stat = " << sigStat );
   }
#endif

   if ( contents )
   {
      MultipartMixedContents* mixed = dynamic_cast<MultipartMixedContents*>(contents);
      if ( mixed )
      {
         InfoLog( << "Got a multipart mixed" );

         contents = NULL;
         
         MultipartMixedContents::Parts& parts = mixed->parts();
         for( MultipartMixedContents::Parts::const_iterator i = parts.begin(); 
              i != parts.end();  
              ++i)
         {
            Contents* c = *i;  
            assert( c );
            InfoLog ( << "mixed has a " << c->getType() );

            if ( c->getType() == Mime("application","sipfrag") )
            {
               InfoLog ( << "mixed has sipfrag " << c->getType() );
           
               SipFrag* frag = dynamic_cast<SipFrag*>(c);
               if ( frag )
               {
                  InfoLog( << "Got a sipFrag inside mixed" );
                  
                  SipMessage& m = frag->message();
                  
                  InfoLog( <<"Frag is " << m );
               }
             }
         }
      }
   }

   if ( contents )
   {
      SipFrag* frag = dynamic_cast<SipFrag*>(contents);
      if ( frag )
      {
         InfoLog( << "Got a sipFrag" );

         SipMessage& m = frag->message();
         
         InfoLog( <<"Frag is " << m );
      }
      else
      {
         InfoLog ( << "Can not handle type " << contents->getType() );

         return;
      }
   }
}


void 
TuIM::processSubscribeRequest(SipMessage* msg)
{
   assert( msg->header(h_RequestLine).getMethod() == SUBSCRIBE );
   CallId id = msg->header(h_CallId);
   
   processSipFrag( msg );
   
   int expires=mSubscriptionTimeSeconds;
   if ( msg->exists(h_Expires) )
   {
      expires = msg->header(h_Expires).value();
   }
   if (expires > mSubscriptionTimeSeconds )
   {
      expires = mSubscriptionTimeSeconds;
   }
   
   DeprecatedDialog* dialog = NULL;

   // see if we already have this subscription
   for ( SubscriberIterator i=mSubscribers.begin(); i != mSubscribers.end(); i++)
   {
      DeprecatedDialog* d = i->dialog;
      assert( d );
      
      if ( d->getCallId() == id )
      {
         // found the subscrition in list of current subscrbtions 
         dialog = d;
         break;
      }
   }
   
   if ( !dialog )
   {
      // create a new subscriber 
      DebugLog ( << "Creating new subscrition dialog ");

      Subscriber s;
      
      s.dialog = new DeprecatedDialog( NameAddr(mContact) );
      dialog = s.dialog;
      
      Uri from = msg->header(h_From).uri();
      s.aor = from.getAorNoPort();

      assert( mCallback );
      s.authorized = mCallback->authorizeSubscription( from );
      
      mSubscribers.push_back( s );
   }

   assert( dialog );
   dialog->setExpirySeconds( expires );
   
   auto_ptr<SipMessage> response( dialog->makeResponse( *msg, 200 ));
 
   response->header(h_Expires).value() = expires;
   response->header(h_Event).value() = Data("presence");
   
   mStack->send( *response );

   sendNotify( dialog );

#if 1
   // do symetric subscriptions 
   // See if this person is our buddy list and if we are not subscribed to them

    UInt64 now = Timer::getTimeMs();
    Uri from = msg->header(h_From).uri();

    for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
    {
       Data buddyAor = i->uri.getAor();
       
       if ( ! (i->presDialog->isCreated()) )
       {
          if (  from.getAor() == i->uri.getAor() )
          {
	    if ( from.getAor() != mAor.getAor() )
	    {
              i->mNextTimeToSubscribe = now;
	    }
          }
       }
    }
#endif
}


void 
TuIM::processRegisterRequest(SipMessage* msg)
{
   assert( msg->header(h_RequestLine).getMethod() == REGISTER );
   CallId id = msg->header(h_CallId);

   int expires = msg->header(h_Expires).value();
   if ( expires == 0 ) 
   { 
      expires = 3600;
   } 

   SipMessage* response = Helper::makeResponse( *msg, 200 );

   // the Contacts from the default Helper are wrong for a Registration
   response->remove(h_Contacts);
   
   if ( msg->exists(h_Contacts) )
   {
      ParserContainer<NameAddr> &providedContacts(msg->header(h_Contacts));

      int multipleContacts = providedContacts.size();

      DebugLog ( << multipleContacts << " contacts were in received message." );   

      ParserContainer<NameAddr>::iterator i(providedContacts.begin());
      for ( ; i != providedContacts.end() ; ++ i) {
         if ( i->isAllContacts() && multipleContacts )  // oops, multiple Contacts and one is "*"
         {
            delete response;  // do I need to do this?
            response = Helper::makeResponse( *msg, 400 );
            mStack->send( *response );
            delete response;
            return;
         }
         if ( !i->exists(p_expires) )  // add expires params where they don't exist
         {
            i->param(p_expires) = expires;
         }
         response->header(h_Contacts).push_back(*i);   // copy each Contact into response
      }
   }
   // else the REGISTER is a query, just send the message with no Contacts

   mStack->send( *response );

   delete response;
}


void 
TuIM::processNotifyRequest(SipMessage* msg)
{
   assert( mCallback );
   assert( msg->header(h_RequestLine).getMethod() == NOTIFY ); 

   processSipFrag( msg );

   auto_ptr<SipMessage> response( Helper::makeResponse( *msg, 200 ));
   mStack->send( *response );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -