📄 tuim.cxx
字号:
#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::SIPusing 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() );}boolTuIM::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;}voidTuIM::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 + -