rcsimengine/src/chatcontactmanagerimpl_sym.cpp
changeset 0 59dfe4ae66d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rcsimengine/src/chatcontactmanagerimpl_sym.cpp	Fri Oct 08 18:07:26 2010 +0530
@@ -0,0 +1,610 @@
+/*
+* Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html."
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+* Contributors:
+*
+* Description:
+* RCS IM Library - Initial version
+*
+*/
+
+
+
+#include <cntdb.h>
+#include <cntfield.h>
+#include <cntitem.h>
+#include <cntfldst.h>
+#include <qcontactmanager.h>
+#include <qcontact.h>
+#include <qcontactdetails.h>
+#include "chatsession.h"
+#include "chatcontactmanager.h"
+#include "chatcontactmanagerimpl_sym.h"
+#include "chatsessionimpl_sym.h"
+#include "msrpchatsessiondata_sym.h"
+#include <chatinterfaces.h>
+#include <sipprofileregistry.h>
+#include <mcesession.h>
+#include "qcontactfilter.h"
+
+using namespace RcsIMLib;
+
+
+ChatContactManagerImpl::ChatContactManagerImpl(ChatContactManager *apCntManager):mParent(apCntManager),mProfile(NULL)
+{
+    QT_TRAP_THROWING(setupMceManagerL());
+    mManager = new QContactManager("symbian");
+	
+	QContact  self = mManager->contact(mManager->selfContactId());
+	//mMyID = self.localId();
+	
+	// To get Self SIP Uri.
+	QContactDetail selfContactDetail = self.detail(QContactOnlineAccount::DefinitionName);
+	const QContactOnlineAccount &onlineUrl = static_cast<const QContactOnlineAccount &>(selfContactDetail);
+	QString selfSipUri = onlineUrl.accountUri();
+	TPtrC16 dataPtr(reinterpret_cast<const TUint16*>(selfSipUri.utf16()));
+	mOriginatorUri = HBufC8::NewL(dataPtr.Length());
+	mOriginatorUri->Des().Copy(dataPtr);
+			
+}
+
+
+ChatContactManagerImpl::~ChatContactManagerImpl()
+    {
+
+    for(int i=0;i<mMceSessions.Count();i++)
+        {
+        
+        int mSessionState =  mMceSessions[i]->State();
+        
+        if (mSessionState <= CMceSession::EEstablished)
+            mMceSessions[i]->TerminateL(0,0,0);
+             
+        }
+    
+    mMceSessions.ResetAndDestroy();//deletes streams, sources and sinks
+    mMceSessions.Close();
+    mChatSessionArray.ResetAndDestroy();
+    mChatSessionArray.Close();
+    delete mManager;
+    delete mMceMgr;
+    
+    //delete mProfile;
+    mAllprofiles.ResetAndDestroy();
+    mAllprofiles.Close();
+    
+    delete mProfileReg;
+    delete mSip;
+    delete mOriginatorUri;
+    
+    }
+
+void ChatContactManagerImpl::closeSession(RcsChatId sessID)
+{
+    
+    CMceSession *currentSession = reinterpret_cast<CMceSession*>(sessID);
+    
+    int mSessionState =  currentSession->State();
+           
+    if (mSessionState == CMceSession::EEstablished)
+        currentSession->TerminateL();
+    
+    //remove and close
+    
+    TInt idx = mMceSessions.Find(currentSession);
+    if (idx != KErrNotFound)
+        {
+        delete currentSession;
+        mMceSessions.Remove(idx);    
+        }
+    
+    for(int i=0;i<mChatSessionArray.Count();i++)
+        {
+           if(mChatSessionArray[i]->iMceSession == currentSession)
+               {
+               delete mChatSessionArray[i];
+               mChatSessionArray.Remove(i);
+               break;
+               }
+        }
+ }
+
+void ChatContactManagerImpl::acceptIncomingSession(RcsChatId sessID)
+{    
+    CMceInSession *currentSession = reinterpret_cast<CMceInSession*>(sessID);
+     if (currentSession->State() == CMceSession::EProceeding)
+      {
+         currentSession->AcceptL();
+      }           
+ }
+
+
+
+RcsIMLib::RcsChatId ChatContactManagerImpl::createChatSession(QContactLocalId contactId, QString initMsg)
+{
+    RcsIMLib::RcsChatId id = 0;
+    QT_TRAP_THROWING(id = createChatSessionL(contactId, initMsg));
+    //QT_TRYCATCH_ERROR(id = createChatSessionL(contactId, initMsg));
+    return id;
+}
+
+
+RcsIMLib::RcsChatId ChatContactManagerImpl::createChatSessionL(QContactLocalId contactId, QString initMsg)
+{             
+    // To get recipient SIP Uri.
+    const QContact buddy = mManager->contact(contactId);
+    QContactDetail buddyContactDetail = buddy.detail(QContactOnlineAccount::DefinitionName);
+    const QContactOnlineAccount &onlineUrl = static_cast<const QContactOnlineAccount &>(buddyContactDetail);
+    QString buddySipUri = onlineUrl.accountUri();
+    TPtrC16 dataPtr(reinterpret_cast<const TUint16*>(buddySipUri.utf16()));
+    HBufC8 *recipientUri = HBufC8::NewL(dataPtr.Length());
+    CleanupStack::PushL(recipientUri);
+    recipientUri->Des().Copy(dataPtr);
+    
+    CMceOutSession *outSess ;
+    if(mProfile)
+        {
+        outSess = CMceOutSession::NewL(*mMceMgr, *mProfile, *recipientUri);
+        }
+    else
+        {        
+        outSess = CMceOutSession::NewL(*mMceMgr, 1,*mOriginatorUri, *recipientUri); 
+        }        
+    CleanupStack::PopAndDestroy(recipientUri);
+    CleanupStack::PushL(outSess);
+    
+    /* Add the out session to the list of MCESessions */
+    mMceSessions.Append(outSess);
+    CleanupStack::Pop(outSess);
+
+    /* Streams Creation */
+    // Create the stream for UpLink and Downlink
+    CMceMessageStream* msgStrmUp = CMceMessageStream::NewL();
+    CleanupStack::PushL(msgStrmUp);
+    
+    // Message Source
+    CMceMessageSource* messageSrc = CMceMessageSource::NewL(*mMceMgr);  
+    CleanupStack::PushL(messageSrc);  
+    
+    //MSRP Sink
+    CMceMsrpSink* msrpSink = CMceMsrpSink::NewL();
+    CleanupStack::Pop(messageSrc);
+    CleanupStack::PushL(msrpSink);
+    CleanupStack::PushL(messageSrc);
+    msgStrmUp->SetSourceL(messageSrc);
+    CleanupStack::Pop(messageSrc);
+
+    // Add sink  to the stream
+    msgStrmUp->AddSinkL(msrpSink);
+    CleanupStack::Pop(msrpSink);
+    msgStrmUp->ConnectionSetUpL(CMceMessageStream::EActive);
+
+    // Set AcceptTypes
+    CDesC8ArrayFlat *acceptTypes = new(ELeave)CDesC8ArrayFlat(KGranularity);
+    _LIT8(KtextPlain,"text/plain");   
+    acceptTypes->AppendL(KtextPlain);    
+
+    msrpSink->SetAcceptTypesL(*acceptTypes);
+    delete acceptTypes;
+
+    _LIT8(KAcceptWrap, "acceptwrap");
+    TBuf8<KAcceptSize> accept(KAcceptWrap);
+    msrpSink->SetAcceptWrappedTypesL(accept);
+
+
+    //outSess->AddStreamL(msgStrmUp);
+    CleanupStack::Pop(msgStrmUp);
+
+
+    // Create the stream for Downlink
+    CMceMessageStream *msgStrmDown = CMceMessageStream::NewL();
+
+    // MSRP Source
+    CMceMsrpSource *msrpSrc = CMceMsrpSource::NewL();
+
+    // Message Sink
+    CMceMessageSink* messageSink = CMceMessageSink::NewL(*mMceMgr);
+    CleanupStack::PushL(msrpSrc);
+    msgStrmDown->SetSourceL(msrpSrc);
+    CleanupStack::Pop(msrpSrc);
+
+    // Add sink  to the stream
+    CleanupStack::PushL(messageSink);
+    msgStrmDown->AddSinkL(messageSink);
+    CleanupStack::Pop(messageSink);
+    msgStrmDown->ConnectionSetUpL(CMceMessageStream::EActive);
+
+    CleanupStack::PushL(msgStrmUp);
+    msgStrmDown->BindL(msgStrmUp);
+    CleanupStack::Pop(msgStrmUp);
+
+    CleanupStack::PushL(msgStrmDown);
+    outSess->AddStreamL(msgStrmDown);
+    CleanupStack::Pop(msgStrmDown);
+    
+    /* A new Chat Session with the Platform specific Init Params */
+    ChatSession *chatSession = new ChatSession();
+
+    /* Create the ChatSession here */
+    TMsrpChatSession *msrpChatSession = new TMsrpChatSession();
+    msrpChatSession->iMceManager = mMceMgr;
+    msrpChatSession->iMceSession = outSess;
+    msrpChatSession->iChatSession = chatSession;
+    msrpChatSession->iStream1 = msgStrmUp;
+    msrpChatSession->iStream2 = msgStrmDown;
+
+    //chatSession->setPlatformParams(msrpChatSession);
+
+    mChatSessionArray.Append(msrpChatSession);
+
+
+    //Start the session establishment here. Emit the signal when everything is
+    //done. The session will be matched my the ID returned.
+    //RcsChatId sessID = (RcsChatId)&outSess;
+    
+    
+    //Create the CDesC8Array with the syntax of the subject header and pass it 
+    //such that the INVITE is constructed with Subject header.
+    
+    CDesC8ArrayFlat *mSIPHeaders = new CDesC8ArrayFlat(20);
+    QString mSubjectHeader = "Subject:"+ initMsg;
+    TPtrC16 mDataPtr(reinterpret_cast<const TUint16*>(mSubjectHeader.utf16()));
+    RBuf8 mChatData;
+    mChatData.Create(300);
+    mChatData.Copy(mDataPtr);
+    
+    mSIPHeaders->AppendL(mChatData);
+    outSess->EstablishL(0,mSIPHeaders,0,0,0);                                                                                                                                                                                                                                                                                                                                                  
+
+    return reinterpret_cast<RcsChatId>(outSess);
+}
+
+void ChatContactManagerImpl::setupMceManagerL()
+{
+    //RFileLogger::Write( KLogDir1, KLogFile1, EFileLoggingModeAppend, _L("setupMceManagerL ChkPt 0") );
+    //Setup MCE For accepting and receiving chat messages
+    mMceMgr = CMceManager::NewL(TUid::Uid(0x10009388), &mDataContainer);
+
+    // Set session observer to get the session related state changes
+    mMceMgr->SetSessionObserver(this);    
+
+    // Set InSession Observer to recieve the incoming session
+    mMceMgr->SetInSessionObserver(this);
+    mMceMgr->SetDataSinkObserver(this);
+
+    TUid appUid;
+    
+    appUid.iUid = 0xA00001EC; //TODO get APPUID Correct
+    TRAPD(errsip, mSip = CSIP::NewL(appUid , *this))
+    //TRAPD(errsip, mSip = CSIP::NewL(TUid::Null(), *this))
+    if (!errsip) {
+        //CleanupStack::PushL(sipClient);
+        mProfileReg = CSIPProfileRegistry::NewL(*mSip, *this);
+        //CleanupStack::Pop(mSip);
+    }
+    
+    //assumes first profile is registered and valid    
+    //CleanupStack::PushL(profileReg);
+    //mProfile = profileReg->DefaultProfileL();
+    
+        
+    //later check for tag matches
+    
+    
+    mProfileReg->ProfilesL(mAllprofiles);
+    if (mAllprofiles.Count())
+    {     
+        mProfile = mAllprofiles[0];
+    }
+    
+    //CleanupStack::PopAndDestroy(profileReg);
+    //CleanupStack::PopAndDestroy(sipClient);
+}
+
+
+void ChatContactManagerImpl::SessionStateChanged( CMceSession& aSession, TMceTransactionDataContainer* aContainer)
+{
+    if (aSession.State() == CMceSession::EEstablished)
+    {       
+        
+        CMceMessageStream* downlinkStr = NULL;
+        CMceMessageStream* uplinkStr = NULL;
+        
+        GetStreams(aSession, uplinkStr, downlinkStr );
+                               
+        if (uplinkStr && uplinkStr->Source() &&
+                uplinkStr->Source()->Type() == KMceMessageSource)
+            {
+            uplinkStr->Source()->DisableL();
+            if (!uplinkStr->Source()->IsEnabled())
+                uplinkStr->Source()->EnableL();
+            }
+        
+        if (downlinkStr && downlinkStr->Sinks().Count() > 0)
+            {
+            // assume only one sink is added
+            downlinkStr->Sinks()[0]->DisableL();
+            if (! downlinkStr->Sinks()[0]->IsEnabled() )
+            downlinkStr->Sinks()[0]->EnableL();
+            }
+        
+        for(int i=0;i<mChatSessionArray.Count();i++)
+            {
+               if(mChatSessionArray[i]->iMceSession == &aSession)
+                   {
+                   mChatSessionArray[i]->iStream1 = uplinkStr;
+                   mChatSessionArray[i]->iStream2 = downlinkStr;
+                   mChatSessionArray[i]->iChatSession->setPlatformParams(mChatSessionArray[i]);
+                   break;
+                   }
+            }
+        
+       
+/*  //can be terminated without establishment
+        // A new Chat Session with the Platform specific Init Params 
+        ChatSession *chatSession = new ChatSession();
+
+         //Create the ChatSession here 
+        TMsrpChatSession *msrpChatSession = new TMsrpChatSession();
+        msrpChatSession->iMceManager = mMceMgr;
+        msrpChatSession->iMceSession = &aSession;
+        msrpChatSession->iChatSession = chatSession;
+        msrpChatSession->iStream1 = uplinkStr;
+        msrpChatSession->iStream2 = downlinkStr;
+
+        chatSession->setPlatformParams(msrpChatSession);
+
+        mChatSessionArray.Append(msrpChatSession);
+*/
+
+        /* Notify the UI that Session is established. Pointer to aSession
+         * serves as the key */
+        for(int i=0;i<mChatSessionArray.Count();i++)
+            {
+               if(mChatSessionArray[i]->iMceSession == &aSession)
+                   {
+                   emit mParent->sessionEstablised(reinterpret_cast<RcsChatId>(&aSession), mChatSessionArray[i]->iChatSession); 
+                   break;
+                   }
+            }
+        
+        
+    }
+    else if (aSession.State() == CMceSession::EProceeding)
+    {
+    //get originator
+    const TDesC8& remoteURI = aSession.Originator();
+    const QString remoteSIPURI = QString::fromUtf8((const char*)remoteURI.Ptr(),remoteURI.Length());
+    
+    //Pass the remote sip uri as a filter and fetch the buddy name. 
+    //Also emit a signal here for incomingChatSession with the contactID 
+
+    // To fetch the buddy name using the sip URI.
+    QList<QContactSortOrder> order;
+    QStringList list;
+    QContactDetailFilter filter;
+    filter.setDetailDefinitionName(QContactOnlineAccount::DefinitionName, QContactOnlineAccount::SubTypeSip);
+    filter.setValue(remoteSIPURI);
+    
+    QList<QContact> allContacts;
+    allContacts = mManager->contacts(filter);
+    unsigned int buddyID = 0;
+    if(allContacts.count())
+        {
+        buddyID = allContacts[0].localId();
+        }
+  
+    QString imMsg;
+	
+
+    for(int i=0;i<mChatSessionArray.Count();i++)
+    {
+       if(mChatSessionArray[i]->iMceSession == &aSession)
+           {
+           imMsg = mChatSessionArray[i]->iInitMsg;
+           break;
+           }
+    }
+    
+     
+    //emit on SSC to proceeding as a result of call to updateL //see insession header
+    //emit after update or could lead to accept call before update, little chance as user interaction involved
+    emit mParent->incomingChatSession(buddyID, remoteSIPURI, imMsg, reinterpret_cast<RcsChatId>(&aSession));
+    }
+    else if (aSession.State() == CMceSession::ETerminated)
+    {
+        for(int i=0;i<mChatSessionArray.Count();i++)
+        {
+           if(mChatSessionArray[i]->iMceSession == &aSession)
+               {
+               emit mParent->sessionTerminated(reinterpret_cast<RcsChatId>(&aSession), mChatSessionArray[i]->iChatSession);
+               break;
+               }
+        }
+    
+    }
+}
+
+
+
+void ChatContactManagerImpl::SessionConnectionStateChanged( CMceSession& , TBool /*aActive*/ )
+{
+}
+
+void ChatContactManagerImpl::Failed( CMceSession& /*aSession*/, TInt /*aError*/ )
+{
+}
+
+void ChatContactManagerImpl::UpdateFailed(CMceSession& /*aSession*/, TMceTransactionDataContainer* /*aContainer*/ )
+{
+}
+
+// From MSIPProfileAgentObserver
+void ChatContactManagerImpl::ProfileRegistryEventOccurred(TUint32 /*aProfileId*/, TEvent /*aEvent*/)
+{
+}
+
+void ChatContactManagerImpl::ProfileRegistryErrorOccurred(TUint32 /*aProfileId*/,  TInt /*aError*/)
+{
+}
+
+// From MSIPObserver
+void ChatContactManagerImpl::IncomingRequest(TUint32 /*aIapId*/, CSIPServerTransaction* /*aTransaction*/)
+{
+}
+
+void ChatContactManagerImpl::TimedOut(CSIPServerTransaction& /*aTransaction*/)
+{
+}
+
+// From MMceInSessionObserver
+void ChatContactManagerImpl::IncomingSession(CMceInSession* aSession, TMceTransactionDataContainer* aContainer )
+{       
+    if (aSession->State() == CMceSession::EIncoming)
+    {
+        ///////////////////////
+        QString imMsg;
+        //Fetch the message from the SIP INVITE
+        CDesC8Array *mSIPHeader = aContainer->GetHeaders(); 
+        TInt count = mSIPHeader->MdcaCount();
+           
+        for (int i=0; i<count; i++)
+        {
+            TPtrC8 data = mSIPHeader->MdcaPoint(i);
+            QString header = QString::fromUtf8((const char*)data.Ptr(),data.Length());
+            if (header.contains("Subject",Qt::CaseSensitive))
+                {
+                    QChar sep = ':';
+                    //QString mChatData = header.section(sep,1);
+                    imMsg = header.section(sep,1);
+                }
+                else 
+                {
+                    //QString mChatData = "";
+                    imMsg = "";
+                }
+        }
+        //////////////////////
+    
+        // get the stream for this incoming session to set the MSRP capabilities
+        CMceMessageStream* downlinkStr = NULL;
+        CMceMessageStream* uplinkStr = NULL;
+        GetStreams(*aSession, uplinkStr, downlinkStr);
+        
+        ChatSession *chatSession = new ChatSession();
+
+        // Create the ChatSession here 
+        TMsrpChatSession *msrpChatSession = new TMsrpChatSession();
+        msrpChatSession->iMceManager = mMceMgr;
+        msrpChatSession->iMceSession = aSession;
+        msrpChatSession->iChatSession = chatSession;
+        msrpChatSession->iStream1 = uplinkStr;
+        msrpChatSession->iStream2 = downlinkStr;
+        msrpChatSession->iInitMsg = imMsg;
+
+        mChatSessionArray.Append(msrpChatSession);
+        
+        
+         if (downlinkStr )
+         {
+            CMceMsrpSource* msrpSource = static_cast<CMceMsrpSource*> (downlinkStr->Source());
+            if(msrpSource)
+             {
+                downlinkStr->ConnectionSetUpL(CMceMessageStream::EPassive);
+                //uplinkStr->ConnectionSetUpL(CMceMessageStream::EPassive);
+
+                // Set AcceptTypes
+                CDesC8ArrayFlat *acceptTypes = new(ELeave)CDesC8ArrayFlat(KGranularity);
+                _LIT8(KtextPlain,"text/plain");
+                _LIT8(KMessageCpim, "message/cpim");
+                acceptTypes->AppendL(KtextPlain);
+                acceptTypes->AppendL(KMessageCpim);
+
+                msrpSource->SetAcceptTypesL(*acceptTypes);
+                delete acceptTypes;
+
+                _LIT8(KAcceptWrap, "acceptwrap");
+               TBuf8<KAcceptSize> accept(KAcceptWrap);
+               msrpSource->SetAcceptWrappedTypesL(accept);
+             }
+          }
+         
+         /* Add the out session to the list of MCESessions */
+         mMceSessions.Append(aSession);
+         aSession->UpdateL();
+       }         
+}
+
+
+void ChatContactManagerImpl::IncomingUpdate(CMceSession& , CMceInSession* , TMceTransactionDataContainer* )
+{
+}
+
+void ChatContactManagerImpl::DataReceived(CMceMediaStream& aStream, CMceMediaSink& /*aSink*/, const TDesC8& aData)
+{
+    /* Find the Session for which this Message is intented */
+    for(int i=0; i<mChatSessionArray.Count(); i++)
+    {
+       if(mChatSessionArray[i]->iStream1 == &aStream || mChatSessionArray[i]->iStream2 == &aStream)
+       {
+           ChatSessionImpl *pImpl = static_cast<ChatSessionImpl*>(mChatSessionArray[i]->iChatSession->getPlatformImpl());
+           pImpl->incomingData(aData);
+       }
+    }
+}
+
+
+void ChatContactManagerImpl::GetStreams(CMceSession& aSession, CMceMessageStream*& aUplinkStr, CMceMessageStream*& aDownlinkStr )
+    {
+    RPointerArray<CMceMediaStream> streams = aSession.Streams();
+    for (TInt i=0; i<streams.Count();i++)
+       {
+       if (streams[i]->Type() == KMceMessage  && 
+               streams[i]->Source() &&
+               streams[i]->Source()->Type() == KMceMSRPSource)
+           {
+           aDownlinkStr =static_cast<CMceMessageStream*> (streams[i]);
+           //break;
+           }
+           
+       if (streams[i]->Type() == KMceMessage  && 
+               streams[i]->Source() &&
+               streams[i]->Source()->Type() == KMceMessageSource)
+           {
+           aUplinkStr =static_cast<CMceMessageStream*> (streams[i]);
+           //break;
+           }  
+       if (aDownlinkStr == NULL && streams[i]->BoundStream())
+           {
+           if (streams[i]->BoundStreamL().Type() == KMceMessage  && 
+                   streams[i]->BoundStreamL().Source() &&
+                   streams[i]->BoundStreamL().Source()->Type() == KMceMSRPSource)
+               {
+               CMceMessageStream& stream =static_cast<CMceMessageStream&> (streams[i]->BoundStreamL());
+               aDownlinkStr =  &stream;
+             //  break;
+               } 
+           }
+           
+       if (aUplinkStr == NULL && streams[i]->BoundStream())
+           {
+           if (streams[i]->BoundStreamL().Type() == KMceMessage  && 
+                   streams[i]->BoundStreamL().Source() &&
+                   streams[i]->BoundStreamL().Source()->Type() == KMceMessageSource)
+               {
+               CMceMessageStream& stream =static_cast<CMceMessageStream&> (streams[i]->BoundStreamL());
+               aUplinkStr =  &stream;
+               } 
+           }
+       }   // for loop
+
+    }
+
+
+