Msrp/MsrpServer/src/CMSRPMsgParser.cpp
branchMSRP_FrameWork
changeset 25 505ad3f0ce5c
child 58 cdb720e67852
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Msrp/MsrpServer/src/CMSRPMsgParser.cpp	Sat Jun 12 14:30:11 2010 +0530
@@ -0,0 +1,1102 @@
+/*
+* 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:
+* MSRP Implementation
+*
+*/
+
+// INCLUDES
+
+// CLASS HEADER
+#include "CMSRPMsgParser.h"
+#include "MSRPCommon.h"
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::NewL
+// Static constructor
+// -----------------------------------------------------------------------------
+//
+/*static*/CMSRPMsgParser* CMSRPMsgParser::NewL(MMSRPParserObserver& aConnection)
+    {
+    MSRPLOG( "CMSRPMsgParser::NewL enter" )
+    CMSRPMsgParser* self = new (ELeave) CMSRPMsgParser(aConnection );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    MSRPLOG( "CMSRPMsgParser::NewL exit" )
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::CMSRPMsgParser
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::CMSRPMsgParser(MMSRPParserObserver& aConnection)        
+    : iConnection( aConnection )
+    {  
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::~CMSRPMsgParser
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::~CMSRPMsgParser()
+    {
+    MSRPLOG( "CMSRPMsgParser::~CMSRPMsgParser enter" )
+    delete iLocalBuf;
+    delete iEndToken;
+    delete iMessage;
+    iParseBuffers.ResetAndDestroy();
+    iParseBuffers.Close();    
+    MSRPLOG( "CMSRPMsgParser::~CMSRPMsgParser exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::ConstructL
+// 2nd phase constructor
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::ConstructL()
+    {
+    iState = ETitleLine;
+    //to avoid leak on newl leave
+    RMsrpBuf buf(iBufPool.ProvideBufferL());
+    iLocalBuf = new (ELeave) RMsrpBuf(buf);
+    //iLocalBuf = new (ELeave) RMsrpBuf(iBufPool.ProvideBufferL());
+    iEndToken = HBufC8::NewL(KMSRPEndTokenMax);   
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::ParseL
+// -----------------------------------------------------------------------------
+//
+TBool CMSRPMsgParser::ParseL()
+    {
+    TMatchType match = EFullMatch;
+    TBool ret = TRUE;
+
+    /*parse until a parse element spans buffers. 
+      if parse element completes exactly at buffer boundaries,
+      might end up parsing greater than bufsize+1_element in one runl. 
+      to avoid, use transitioned flag (set in handle full match)*/
+    while (match == EFullMatch) 
+    //while (ret == TRUE)/*parse all parseable data*/
+        {    
+        MSRPLOG( "CMSRPMsgParser::ParseL enter" )    
+        if(!iParseBuffers.Count())
+		{
+			MSRPLOG( "CMSRPMsgParser::ParseL exit" ) 
+            return FALSE;
+		}
+                               
+        TPtrC8 token(KCRAndLF());        
+        if (iState == EBody)
+            {
+            token.Set(iEndToken->Des());                
+            }   
+        
+        TInt matchPos;
+        match = FindToken(iParseBuffers[0]->Ptr(),token,matchPos);    
+        if(match == EFullMatch)
+            {
+            ret = HandleFullMatchL(token, matchPos);
+            }
+        else if (match == EPartialMatch)
+            {
+            ret = HandlePartialMatchL(token, matchPos);    
+            }
+        else //if (match == ENoMatch)        
+            {              
+            ret = HandleNoMatchL(token, matchPos);
+            }
+        }
+    MSRPLOG( "CMSRPMsgParser::ParseL exit" )
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleFullMatchL
+// -----------------------------------------------------------------------------
+//
+TBool CMSRPMsgParser::HandleFullMatchL(TPtrC8& aToken, TInt aMatchPos, TBool aCopyToLocal)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleFullMatchL enter" )
+    
+    TPtrC8 buf = iParseBuffers[0]->Ptr().Left(aMatchPos + aToken.Length());
+    if(aCopyToLocal)
+        {        
+        iLocalBuf->Append(buf);
+        }
+    else
+        {
+        HandleStateL(buf, aMatchPos);
+        }
+    
+    if((aMatchPos + aToken.Length()) != iParseBuffers[0]->Ptr().Length())
+        {
+        iParseBuffers[0]->MsrpMidTPtr(aMatchPos + aToken.Length());
+        }
+    else
+        {
+        //transitioned
+        RMsrpBuf* headBuf = iParseBuffers[0];
+        iParseBuffers.Remove(0);
+        delete headBuf;
+        if(!iParseBuffers.Count())
+            return FALSE;
+        }
+    MSRPLOG( "CMSRPMsgParser::HandleFullMatchL exit" )
+    return TRUE;
+    }
+    
+    
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandlePartialMatchL
+// -----------------------------------------------------------------------------
+//
+TBool CMSRPMsgParser::HandlePartialMatchL(TPtrC8& aToken, TInt aCurBufMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandlePartialMatchL enter" )
+    TBool ret = TRUE;
+    TInt matchTokenLen = iParseBuffers[0]->Ptr().Length()- aCurBufMatchPos;
+    TPtrC8 matchToken = aToken.Left(matchTokenLen);
+    TPtrC8 remainingToken = aToken.Mid(matchTokenLen);
+    TPtrC8 emptyToken;
+    
+    if(iParseBuffers.Count() < 2)
+        {
+        if (iState == EBody && aCurBufMatchPos)
+            //if some bytes to return in body, return now (xcluding token part) rather than parse again 
+            {            
+            ret = HandleFullMatchL(emptyToken, aCurBufMatchPos);//parse true return nxt parse false
+            }
+        return FALSE;//buffer count greater than 0 but content size smaller than complete lexical element  
+        }
+    
+    //Look to complete token
+    TInt nxtBufMatchPos;
+    TMatchType match;                      
+    TPtrC8 headOfNxtBuf = iParseBuffers[1]->Ptr().Left(remainingToken.Length());                    
+    match = FindToken(headOfNxtBuf, remainingToken, nxtBufMatchPos);                       
+    
+    if(nxtBufMatchPos!=0) //nxt buf does not complete token
+        {
+        if (iState != EBody)
+            {
+            User::LeaveIfError(KErrCorrupt);
+            }
+        //false partial alarm for body, dont retain token part
+        //need to update curbuf as false tokenpart also needs to be returned
+        aCurBufMatchPos += matchToken.Length();
+        //ret = HandleFullMatchL(matchToken, aCurBufMatchPos);//parse true return true
+        ret = HandleFullMatchL(emptyToken, aCurBufMatchPos);
+        }
+    else
+        {
+        if(match == EPartialMatch) //completes part token but bytes insufficient
+            {
+            if (iState == EBody && aCurBufMatchPos)
+                {
+                ret = HandleFullMatchL(emptyToken, aCurBufMatchPos);//parse true ret false                                   
+                }            
+            return FALSE;
+            }
+        else //complete token
+            {  
+            TBool addToLocal = FALSE;
+            if(iState != EBody)
+                {
+                addToLocal = TRUE;                
+                }
+
+            ret = HandleFullMatchL(matchToken, aCurBufMatchPos, addToLocal);
+            ret = HandleFullMatchL(remainingToken, nxtBufMatchPos, addToLocal);//if token.length() and matches state token upto length, transition state
+            //ret cud be false, if nxtbuf exactly completes token
+
+            if(addToLocal == TRUE)
+                {
+                HandleStateL(*iLocalBuf, aCurBufMatchPos+nxtBufMatchPos);//nxtBuf==0, just token
+                iLocalBuf->Zero();
+                }            
+            }
+        }
+    MSRPLOG( "CMSRPMsgParser::HandlePartialMatchL exit" )
+    return ret;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleNoMatchL
+// -----------------------------------------------------------------------------
+//
+TBool CMSRPMsgParser::HandleNoMatchL(TPtrC8& aToken, TInt aCurBufMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleNoMatchL enter" )
+
+    TPtrC8 emptyToken;    
+    TBool ret = FALSE;
+    
+    aCurBufMatchPos = iParseBuffers[0]->Ptr().Length();
+    
+    if (iState == EBody /*&& aCurBufMatchPos*/)
+        {        
+        ret = HandleFullMatchL(emptyToken, aCurBufMatchPos);        
+        }        
+    else if(iParseBuffers.Count() >= 2)
+        {
+        //if header find token in nxt buf
+        TInt nxtBufMatchPos;
+        TMatchType match;                      
+        match = FindToken(iParseBuffers[1]->Ptr(),aToken,nxtBufMatchPos);
+        
+        if(match == EFullMatch)
+            {       
+            ret = HandleFullMatchL(emptyToken, aCurBufMatchPos, TRUE);
+            ret = HandleFullMatchL(aToken, nxtBufMatchPos, TRUE);
+            HandleStateL(*iLocalBuf, aCurBufMatchPos+nxtBufMatchPos);
+            iLocalBuf->Zero();
+            }
+        else if (iParseBuffers.Count()>2)
+            {
+            User::LeaveIfError(KErrCorrupt);        
+            }
+        //else count==2, bytes insufficient in nxt buf, return false        
+        }
+    MSRPLOG( "CMSRPMsgParser::HandleNoMatchL exit" )
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleStateL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleStateL(const TDesC8& aString, TInt aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleStateL enter" )
+    switch(iState)
+         {
+         case ETitleLine:
+             HandleTitleLineL(aString, aMatchPos);             
+             break;
+         
+         case EToPath:
+         case EFromPath:    
+         //case EMandatoryHeader:
+             HandleHeaderL(aString, aMatchPos);            
+             break;
+                          
+         case EOptionalHeaders:
+             HandleOptionalHeaderL(aString, aMatchPos);
+             break;
+                                      
+         case EExtraCRLF:
+             HandleXtraCrlfL(aString, aMatchPos);
+             break;
+             
+         case EBody:
+             HandleBodyL(aString, aMatchPos);
+             break;             
+             
+         case EEndofEndLine:
+             HandleEndofEndLineL(aString, aMatchPos);
+             break;
+                          
+         default:
+             User::LeaveIfError(KErrUnknown);
+             break;        
+         }   
+    MSRPLOG( "CMSRPMsgParser::HandleStateL exit" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleTitleLineL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleTitleLineL(const TDesC8& aString, TInt /*aMatchPos*/)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleTitleLineL enter" )
+    TPtrC8 msrp(aString.Left(KMSRP().Length()));
+    if(msrp.Compare(KMSRP()))
+        User::LeaveIfError(KErrCorrupt);
+    if(aString[KMSRP().Length()] != ' ')
+        User::LeaveIfError(KErrCorrupt);
+    
+    TPtrC8 trans_id = aString.Mid(KMSRP().Length()+1);    
+    TInt pos = trans_id.Locate(MSRP_SPACE);
+    /*if(pos == KErrNotFound)
+        User::LeaveIfError(KErrCorrupt);*/    
+    if (pos < KMSRPIDLenMin || pos > KMSRPIDLenMax)
+        User::LeaveIfError(KErrCorrupt);           
+    trans_id.Set(trans_id.Left(pos));
+    
+    TPtr8 ptr = iEndToken->Des();
+    ptr.Zero();
+    ptr.Append(KCRAndLF);
+    ptr.Append(KDashLine());
+    ptr.Append(trans_id);
+    
+    TPtrC8 method = aString.Mid(KMSRP().Length()+1+trans_id.Length()+1);
+    pos = method.Locate(MSRP_SPACE);
+    
+    if(pos == KErrNotFound)
+        {
+        pos = method.Locate(MSRP_CARRIAGE);        
+    
+        if(pos == KErrNotFound)
+            User::LeaveIfError(KErrCorrupt);
+        
+        method.Set(method.Left(pos));
+                
+         if (!method.Compare(KMSRPSend()))
+             {
+             iMessage = CMSRPMessageHandler::NewL(MMSRPIncomingMessage::EMSRPMessage);
+             }
+         else if (!method.Compare(KMSRPReport()))
+             {
+             iMessage = CMSRPMessageHandler::NewL(MMSRPIncomingMessage::EMSRPReport);
+             }
+         else //extn
+             {
+             iMessage = CMSRPMessageHandler::NewL(MMSRPIncomingMessage::EMSRPNotDefined);
+             }        
+        }
+    else //response
+        {
+        TPtrC8 null;
+        method.Set(method.Left(pos));
+        iMessage = CMSRPMessageHandler::NewL(MMSRPIncomingMessage::EMSRPResponse);
+        iMessage->SetStatusOfResponseL(method, null);
+        }    
+    iMessage->SetTransactionId(trans_id);
+    iState = EToPath;    
+    MSRPLOG( "CMSRPMsgParser::HandleTitleLineL exit" )
+    }
+
+#if 0
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleTitleLineL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleTitleLineL(const TDesC8& aString, TInt /*aMatchPos*/)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleTitleLineL enter" )
+    TLex8 lex(aString);
+
+    //MSRP
+    lex.Mark();
+    lex.SkipCharacters();
+    if(lex.TokenLength() != 4)
+        {   
+        User::LeaveIfError(KErrCorrupt);
+        }    
+    TPtrC8 first_token = lex.MarkedToken();        
+    if (first_token.Compare(KMSRP()))
+        {
+        User::LeaveIfError(KErrCorrupt);
+        }
+    
+    //SP
+    if(lex.Peek() != MSRP_SPACE)
+    {
+    User::LeaveIfError(KErrCorrupt);
+    }
+    lex.Inc();
+    
+    //trans-id
+    lex.Mark();
+    lex.SkipCharacters();    
+    if (lex.TokenLength() < KMSRPIDLenMin || lex.TokenLength() > KMSRPIDLenMax)
+        {
+        User::LeaveIfError(KErrCorrupt);
+        }
+    
+    //SP
+    if(lex.Peek() != MSRP_SPACE)
+    {
+    User::LeaveIfError(KErrCorrupt);
+    }
+    lex.Inc();
+    
+    TPtrC8 trans_id = lex.MarkedToken();
+    TPtr8 ptr = iEndToken->Des();
+    ptr.Zero();
+    ptr.Append(kEndMarker());
+    ptr.Append(trans_id);
+    
+    //method
+    lex.Mark();
+    lex.SkipCharacters();
+    if(lex.TokenLength() != 0)
+        {   
+        User::LeaveIfError(KErrCorrupt);
+        }      
+    TPtrC8 method = lex.MarkedToken();      
+    
+    //create msg
+    //set trans_id
+    if (!method.Compare(KMSRPSend()))
+        {
+        //type = ESend        
+        //set type
+        }
+    else if (!method.Compare(KMSRPReport()))
+        {
+        //type = EReport        
+        //set type
+        }
+    else //if 3 digit string
+        { 
+        //type = EResponse
+        //set type
+        //set status code
+        
+        //remaining SP comment\r\n
+        /*ignore comment*/
+                     
+        }
+    //else extn method
+    
+    //remaining \r\n
+    //TODO: comment, extn method and check remaining bytes is as xpected
+        
+    iState = EToPath;
+    
+    MSRPLOG( "CMSRPMsgParser::HandleTitleLineL exit" )
+    }
+#endif
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleHeaderL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleHeaderL(const TDesC8& aString, TInt /*aMatchPos*/)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleHeaderL enter" )
+    TInt pos = aString.Locate(MSRP_COLON);
+    if(pos == KErrNotFound)
+        User::LeaveIfError(KErrCorrupt);
+    
+    TPtrC8 header_name = aString.Left(pos);
+    TUint8 nxtChar = aString[pos+1];
+       
+    if(nxtChar != MSRP_SPACE)
+        User::LeaveIfError(KErrCorrupt);
+    
+    TPtrC8 header_val = aString.Mid(pos+2); 
+    header_val.Set(header_val.Left(header_val.Length()-2));
+    
+    if(!header_val.Length())
+        User::LeaveIfError(KErrCorrupt);
+
+    MMSRPMessageHandler::TMsrpHeaderType headerType = MMSRPMessageHandler::EHeaderUnknown;
+    if(iState == EToPath)
+        {        
+        if(header_name.Compare(KMSRPToPath()))
+            User::LeaveIfError(KErrCorrupt);
+        headerType = MMSRPMessageHandler::EToPath;
+        iState = EFromPath;
+        }
+    else if(iState == EFromPath)
+        {
+        headerType = MMSRPMessageHandler::EFromPath;
+        if(header_name.Compare(KMSRPFromPath()))
+            User::LeaveIfError(KErrCorrupt);  
+        iState = EOptionalHeaders;
+        }
+    else //find header id
+        {
+        if(!header_name.Compare(KMSRPMessageID()))
+            {            
+            headerType = MMSRPMessageHandler::EMessageId;
+            }
+        else if(!header_name.Compare(KMSRPByteRange()))
+            {
+            headerType = MMSRPMessageHandler::EByteRange;
+            }
+        else if(!header_name.Compare(KMSRPSuccessReport()))
+            {
+            headerType = MMSRPMessageHandler::ESuccessReport;
+            }            
+        else if(!header_name.Compare(KMSRPFailureReport()))
+            {
+            headerType = MMSRPMessageHandler::EFailureReport;
+            }            
+        else if(!header_name.Compare(KMSRPStatus()))
+            {
+            headerType = MMSRPMessageHandler::EStatus;
+            }
+        else if(!header_name.Compare(KMSRPContentType()))
+            {
+            headerType = MMSRPMessageHandler::EContentType;
+            iState = EExtraCRLF;             
+            }           
+        }      
+    
+    //message->add_header
+    TPtrC8 fullHeader(aString);
+    iMessage->AddHeaderL(headerType, header_val, fullHeader);
+    //TODO: //only for to-path from-path add_header error
+    //switch iState = EBody, mode = EError //essentially start looking for end token
+    //if mode is error don't issue callbacks, on transition from EndofEndLine,
+    //delete message and switch to normal mode
+    
+    MSRPLOG( "CMSRPMsgParser::HandleHeaderL exit" )
+        
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleOptionalHeaderL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleOptionalHeaderL(const TDesC8& aString, TInt aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleOptionalHeaderL enter" )
+    TPtrC8 endTokenwoStartCrlf = (*iEndToken).Mid(KCRAndLF().Length()); 
+    TPtrC8 fullToken(aString.Left(endTokenwoStartCrlf.Length()));
+    if (fullToken.Compare(endTokenwoStartCrlf))
+        {
+        HandleHeaderL(aString,aMatchPos);
+        return;
+        }
+    //iState = EEndOfEndLine;
+    aMatchPos -= fullToken.Length();
+    HandleEndofEndLineL(aString.Mid(fullToken.Length()),aMatchPos);
+    MSRPLOG( "CMSRPMsgParser::HandleOptionalHeaderL exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleXtraCrlfL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleXtraCrlfL(const TDesC8& /*aString*/, TInt aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleXtraCrlfL enter" )
+    if(aMatchPos)
+        User::LeaveIfError(KErrCorrupt);
+    iState = EBody;
+    MSRPLOG( "CMSRPMsgParser::HandleXtraCrlfL exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleBodyL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleBodyL(const TDesC8& aString, TInt aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleBodyL enter" )
+    TPtrC8 token = aString.Mid(aMatchPos);
+    
+    //if(!aString.Length())
+     //   return;
+    
+    if(aMatchPos!=0)
+        {
+        TPtrC8 content(aString.Left(aMatchPos));
+        iMessage->AddContentL(content);       
+        }
+
+    //partial or full match
+    if(token.Length())
+        {   
+         
+        //if(aMatchPos == 0)
+            {
+            //TPtrC8 firstPart = (*iEndToken).Left(token.Length());
+            TPtrC8 lastPart = (*iEndToken).Right(token.Length());
+            
+            //if(firstPart == lastPart)
+            /*Solns: set iFlagFirstPartMatch on first match and then transition                      
+              false transition to endline and transition back to body on endline parse error
+              add initial \r\n (disallowed in trans_id) to searchEndToken on transition to body - 
+              for optional header, token has no init crlf*/                    
+            
+            
+            
+            if (!token.Compare(lastPart))
+                {
+                iState = EEndofEndLine;
+                }
+            /*else if(!token.Compare(firstPart)); 
+            else User::LeaveIfError(KErrCorrupt);*/                                                        
+            }
+        //else //full token matches
+        }
+    MSRPLOG( "CMSRPMsgParser::HandleBodyL exit" )
+    return; 
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleEndofEndLineL
+// -----------------------------------------------------------------------------
+//
+void CMSRPMsgParser::HandleEndofEndLineL(const TDesC8& aString, TInt aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::HandleEndofEndLineL enter" )
+    if(aMatchPos != 1)
+        User::LeaveIfError(KErrCorrupt);
+    
+    MMSRPMessageHandler::TMsrpMsgEndStatus endType = MMSRPMessageHandler::EMessageEnd;  
+    if(aString[0] == MSRP_END)
+        endType = MMSRPMessageHandler::EMessageEnd;        
+    else if (aString[0] == MSRP_CONTINUE)
+        endType = MMSRPMessageHandler::EMessageContinues;
+    else if (aString[0] == MSRP_TERMINATE)
+        endType = MMSRPMessageHandler::EMessageTerminated;
+    else
+        User::LeaveIfError(KErrCorrupt);
+    
+    iMessage->EndOfMessageL(endType);
+    iConnection.ParseStatusL( iMessage, KErrNone);
+    iMessage = NULL;
+        
+    iState = ETitleLine;
+    MSRPLOG( "CMSRPMsgParser::HandleEndofEndLineL exit" )    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::FindToken
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::TMatchType CMSRPMsgParser::FindToken( const TDesC8& aString, const TDesC8& aToken, TInt& aMatchPos)
+    {
+    MSRPLOG( "CMSRPMsgParser::FindToken enter" )
+    TMatchType ret = ENoMatch;
+    aMatchPos = KErrNotFound;
+    if(!aString.Length() || !aToken.Length())
+        return ret;
+    aMatchPos = aString.Find(aToken);
+    
+    if(aMatchPos == KErrNotFound)
+        {
+        TUint8 lastChar = aString[aString.Length()-1];
+        TPtrC8 tempToken;
+        tempToken.Set(aToken);
+        
+        TInt tokenPos = tempToken.LocateReverse(lastChar);
+        while (tokenPos != KErrNotFound)
+            {
+            TPtrC8 headPartofToken = tempToken.Left(tokenPos+1);
+            TPtrC8 tailPartofString = aString.Right(tokenPos+1);
+             if(!headPartofToken.Compare(tailPartofString))
+                 break;            
+             tempToken.Set(tempToken.Left(tokenPos)); //if 0
+             tokenPos = tempToken.LocateReverse(lastChar);
+            }
+        if(tokenPos != KErrNotFound)
+            {
+            ret = EPartialMatch;
+            aMatchPos = aString.Length() - (tokenPos+1);
+            }
+        return ret;
+        }    
+    MSRPLOG( "CMSRPMsgParser::FindToken exit" )
+    return EFullMatch;    
+    }
+
+
+//test cases
+//shyamprasad, prasad, xyz, add, dan, shyamprasad
+//pr, prasad
+
+#if 0
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::ExecuteStateL
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::ExecuteStateL()
+    {         
+    TDataCheck ret = EWaitForDataPost; 
+    
+    switch(iState)
+        {
+        case ETitleLine:
+            ret = HandleTitleLineL();
+            break;
+        
+        case EToPath:
+        case EFromPath:    
+        case EMandatoryHeader:
+            ret = HandleMandatoryHeaderL();            
+            break;
+            
+            
+        case EOptionalHeaders:
+            //ret = HandleOptionalHeaderL();
+            break;
+            
+            
+        case EBody:
+            
+            break;
+            
+        default:
+            User::LeaveIfError(KErrUnknown);
+            break;        
+        }    
+      return ret;     
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleTitleLineL
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::HandleTitleLineL()
+    {
+    TDataCheck ret;
+    
+    VARS(lex, transitioned, base_offset, lex_bytesdone);
+    SET_LEX(lex);
+        
+    TOKEN(first_token);            
+    ret = GetNextToken(lex, transitioned, first_token, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_SPACE);//if transitioned, set mode local, being done above based on local buf length
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    
+    if(first_token.iLength == 4)
+        {        
+        FETCH_TOKENSTRING(first_string, first_token, transitioned);
+        if (first_string.Compare(KMSRP()))
+            {
+            User::LeaveIfError(KErrCorrupt);
+            }        
+        }        
+    else
+        {
+        User::LeaveIfError(KErrCorrupt);
+        }
+    
+    TOKEN(trans_id);
+    ret =  GetNextToken(lex, transitioned, trans_id, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_SPACE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    if (trans_id.iLength < KMSRPIDLenMin || trans_id.iLength > KMSRPIDLenMax)
+        {
+        User::LeaveIfError(KErrCorrupt);
+        }
+    
+    TOKEN(method);
+    ret =  GetNextToken(lex, transitioned, method, base_offset, lex_bytesdone);
+    FETCH_TOKENSTRING(method_string, method, transitioned);
+      
+    if (!method_string.Compare(KMSRPSend()))
+        {
+        RET_CHECK(ret,lex,MSRP_CARRIAGE);
+        LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+        //create msg with correct type
+        }
+    else if (!method_string.Compare(KMSRPReport))
+        {
+        RET_CHECK(ret,lex,MSRP_CARRIAGE);
+        LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+        //create msg with correct type
+        }
+    else //if 3 digit string
+        {        
+        RET_CHECK_LENIENT(ret,lex,MSRP_SPACE,val);
+        if (val)
+            {
+            LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+            TOKEN(reason);
+            ret =  GetNextToken(lex, transitioned, reason, base_offset, lex_bytesdone);
+            }
+        RET_CHECK(ret,lex,MSRP_CARRIAGE);
+        LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+        //create msg with correct type
+        //set status code == method_string
+        }
+    //else extn method, TODO
+    
+    //set trans_id
+        
+    //EOL data sufficiency and increment
+    ret = IsDataSufficient(lex, transitioned, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_NEWLINE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+             
+    STATE_COMPLETE(EToPath, lex_bytesdone);    
+    return ret;    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleMandatoryHeaderL
+// -----------------------------------------------------------------------------
+//
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::HandleMandatoryHeaderL()
+    {
+    TDataCheck ret;    
+    VARS(lex, transitioned, base_offset, lex_bytesdone);
+    SET_LEX(lex);
+        
+    TOKEN(header);            
+    ret = GetNextToken(lex, transitioned, header, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_SPACE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    TOKEN(header_val);
+    ret =  GetNextToken(lex, transitioned, header_val, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_CARRIAGE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+
+    //EOL data sufficiency and increment
+    ret = IsDataSufficient(lex, transitioned, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_NEWLINE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    FETCH_TOKENSTRING(header_string, header, transitioned);
+    FETCH_TOKENSTRING(val_string, header_val, transitioned);
+    
+    //check last char is colon and reduce string len by 1
+    //HEADER_CHECK(header_string);
+            
+    switch (iState)
+        {
+        case EToPath:
+            if (header_string.Compare(KMSRPToPath()))
+                {
+                User::LeaveIfError(KErrCorrupt);
+                }
+            //AddHeader callback
+            STATE_COMPLETE(EFromPath, lex_bytesdone);            
+            break;
+            
+        case EFromPath:
+            if (header_string.Compare(KMSRPFromPath()))
+                {
+                User::LeaveIfError(KErrCorrupt);
+                }               
+            //AddHeader callback
+            STATE_COMPLETE(EMandatoryHeader, lex_bytesdone); 
+            break;
+            
+        case EMandatoryHeader:
+            //Findheaderid and give appropriate callback
+            STATE_COMPLETE(EOptionalHeaders, lex_bytesdone);
+            break;
+            
+        default:
+            User::LeaveIfError(KErrUnknown);
+            break;
+        }       
+    return ret; 
+    }
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::HandleOptionalHeaderL
+// -----------------------------------------------------------------------------
+//
+#if 0
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::HandleOptionalHeaderL()
+    {
+    //get first token compare against endline
+    //if yes msg done and handover bodiless msg to conn
+    //if not, get next token and give header callback
+    
+    TDataCheck ret;    
+    VARS(lex, transitioned, base_offset, lex_bytesdone);
+    SET_LEX(lex);
+        
+    TOKEN(header);            
+    ret = GetNextToken(lex, transitioned, header, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_SPACE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    TOKEN(header_val);
+    ret =  GetNextToken(lex, transitioned, header_val, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_CARRIAGE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+
+    //EOL data sufficiency and increment
+    ret = IsDataSufficient(lex, transitioned, base_offset, lex_bytesdone);
+    RET_CHECK(ret,lex,MSRP_NEWLINE);
+    LEX_INC_AVAILABLE(lex, lex_bytesdone, transitioned);
+    
+    FETCH_TOKENSTRING(header_string, header, transitioned);
+    FETCH_TOKENSTRING(val_string, header_val, transitioned);
+    
+    //check last char is colon and reduce string len by 1
+    HEADER_CHECK(header_string);
+            
+    switch (iState)
+        {
+        case EToPath:
+            if (header_string.Compare(KMSRPToPath()))
+                {
+                User::LeaveIfError(KErrCorrupt);
+                }
+            //AddHeader callback
+            STATE_COMPLETE(EFromPath, lex_bytesdone);            
+            break;
+            
+        case EFromPath:
+            if (header_string.Compare(KMSRPFromPath()))
+                {
+                User::LeaveIfError(KErrCorrupt);
+                }               
+            //AddHeader callback
+            STATE_COMPLETE(EMandatoryHeader, lex_bytesdone); 
+            break;
+            
+        case EMandatoryHeader:
+            //Findheaderid and give appropriate callback
+            STATE_COMPLETE(EOptionalHeaders, lex_bytesdone);
+            break;
+            
+        default:
+            User::LeaveIfError(KErrUnknown);
+            break;
+        }       
+    return ret; 
+    }
+
+#endif
+
+    
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::GetNextToken
+// -----------------------------------------------------------------------------
+//
+//TBD: convert to macros
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::GetNextToken(TLex8& aLex, TBool& aTransitioned, TToken& aToken, TInt& aBaseOffset, TInt& aLexBytesDone)
+    {
+    TDataCheck ret = EContinueNormal;
+    
+    aLex.Mark();
+    aToken.iOffset += aBaseOffset + aLex.MarkedOffset();
+    do
+        {
+        aLex.SkipCharacters();        
+        if (aLex.TokenLength() > 0)
+            {    
+            aLexBytesDone += aLex.TokenLength();
+            aToken.iLength += aLex.TokenLength();
+            TPtrC8 tokenString = aLex.MarkedToken();
+            if(aTransitioned)
+                {
+                //TODO: leave or parse error if append not possible 
+                iLocalBuf->Ptr().Append(tokenString);
+                }                        
+            }            
+        ret = IsDataSufficient(aLex, aTransitioned, aBaseOffset, aLexBytesDone); 
+        //if(ret == EContinueTransitioned) aBytesParsed = 0;        
+        } while (ret == EContinueTransitioned);
+        
+    return ret;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMSRPMsgParser::IsDataSufficient
+// not called if in Body, only header data sufficiency check
+// -----------------------------------------------------------------------------
+//TBD: convert to macro
+CMSRPMsgParser::TDataCheck CMSRPMsgParser::IsDataSufficient(TLex8& aLex, TBool& aTransitioned, TInt& aBaseOffset, TInt& aLexBytesDone)
+    {
+    if(aLex.Peek() == 0)
+        {  
+        /*iParseBuffers[0] being parsed*/
+        aBaseOffset += iParseBuffers[0]->Ptr().Length();
+        aLexBytesDone = 0;
+        if(aTransitioned)
+            {
+            delete iParseBuffers[0];
+            }
+        else
+            {
+            if (iMode == EQueueBuf)
+                {
+                /*non collated buffer existence means spanning across buf pools*/  
+                if (iParseBuffers.Count() < 2)
+                    return EWaitForDataPost; //aLexBytesDone =0, nothing copied to local buf
+                else if (iSthgParsed)
+                    return EContinueInNextParse; //aLexBytesDone =0
+                else
+                    iLocalBuf->Ptr().Append(*iParseBuffers[0]);
+                }    
+            /*in case of localbuf, we are about to begin parsing first buf and copy tokens*/
+            aTransitioned = TRUE;
+            }
+        
+#if 0        
+        /*for queuebuf avoid copying till bufpool spanning of a parse element can be confirmed*/
+        if (iMode == EQueueBuf)
+            {
+            if (!aTransitioned)
+                {
+                /*non collated buffer existence means spanning across buf pools*/  
+                if (iParseBuffers.Count() < 2)
+                    return EWaitForDataPost; //aLexBytesDone =0, nothing copied to local buf
+                else if (iSthgParsed)
+                    return EContinueInNextParse; //aLexBytesDone =0
+                else
+                    {                    
+                    //copy to local
+                    aTransitioned = TRUE;
+                    iLocalBuf->Ptr().Append(*iParseBuffers[0]);
+                    aBaseOffset += iParseBuffers[0]->Ptr().Length();
+                    aLexBytesDone = 0;
+                    delete iParseBuffers[0];                    
+                    }
+                }
+            else //once transitioned tokens are being copied,iParseBuffers[0] being parsed, hence no existence check            
+                {
+                //only free
+                aBaseOffset += iParseBuffers[0]->Ptr().Length();
+                aLexBytesDone = 0;
+                delete iParseBuffers[0];                    
+                }            
+            }
+        else //if (iMode == ELocalBuf)
+            {
+            if (!aTransitioned)
+               {
+               /*sthg parsed is always false for local buf*/
+               /*also if not transitioned in this pass, means count of buffers in queue is atleast 1*/               
+               /*if (iParseBuffers.Count() < 1)
+                   return EWaitForDataPost;
+               else if (iSthgParsed)
+                   return EContinueInNextParse;*/
+               //no action  
+               aTransitioned = TRUE;
+               aBaseOffset += iParseBuffers[0]->Ptr().Length();
+               aLexBytesDone = 0;
+               }
+           else //once transitioned tokens are being copied,iParseBuffers[0] being parsed, hence no existence check
+               {
+               //only free  
+               aBaseOffset += iParseBuffers[0]->Ptr().Length();
+               aLexBytesDone = 0;
+               //delete iParseBuffers[0];
+               }                    
+            }
+#endif                       
+        if(!iParseBuffers.Count())
+            return EWaitForDataPost; //aLexBytesDone = 0 //no rbuf to delete
+                                                        
+        //reassign lex to zeroth
+        aLex.Assign(*iParseBuffers[0]);
+        
+        return EContinueTransitioned;
+        }
+    return EContinueNormal;
+    }
+    
+#endif