realtimenetprots/sipfw/SIP/Codec/src/CSIPMessageParser.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Codec/src/CSIPMessageParser.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,262 @@
+// Copyright (c) 2004-2009 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:
+// Name          : CSIPMessageParser.cpp
+// Part of       : SIP Codec
+// Version       : SIP/4.0 
+//
+
+
+
+#include "sipmessageparser.h"
+#include "CSIPPreParser.h"
+#include "TSIPHeaderNameValueIter.h"
+#include "CSIPHeaderNameValue.h"
+#include "SIPHeaderLookup.h"
+#include "sipcodecerr.h"
+#include "sipmessage.h"
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "sipheaderbase.h"
+#include "sipuri.h"
+#include "uricontainer.h"
+#include "_sipcodecdefs.h"
+
+_LIT8(KSIPWithSlash, "SIP/");
+
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::NewL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSIPMessageParser* CSIPMessageParser::NewL ()
+	{
+	CSIPMessageParser* self= CSIPMessageParser::NewLC ();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::NewLC
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSIPMessageParser* CSIPMessageParser::NewLC ()
+	{
+	CSIPMessageParser* self=new(ELeave) CSIPMessageParser;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::CSIPMessageParser
+// -----------------------------------------------------------------------------
+//
+CSIPMessageParser::CSIPMessageParser()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPMessageParser::ConstructL ()
+	{
+	SIPHeaderLookup::OpenL ();
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::~CSIPMessageParser
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSIPMessageParser::~CSIPMessageParser()
+	{
+	SIPHeaderLookup::Close ();
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::FromText
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CSIPMessageParser::FromText (HBufC8* aInputSIPMessage,
+										   CSIPMessage** aSIPMessage)
+	{
+	TInt parseErrorInHeaders=KErrNone;
+	CSIPMessage* sipMessage = 0;
+	TRAPD (err, sipMessage = FromTextL (aInputSIPMessage,parseErrorInHeaders));
+	*aSIPMessage = sipMessage;
+	if (err == KErrNone)
+	    {
+	    err = parseErrorInHeaders;    
+	    }
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::FromTextL
+// -----------------------------------------------------------------------------
+//
+CSIPMessage* CSIPMessageParser::FromTextL (HBufC8* aInputSIPMessage,
+										   TInt& aParseErrorInHeaders)
+	{
+	__ASSERT_ALWAYS (aInputSIPMessage != 0, User::Leave(KErrArgument));
+
+	aParseErrorInHeaders = KErrNone;
+	CSIPPreParser* preParser = CSIPPreParser::NewL(aInputSIPMessage);
+	CleanupStack::PushL(preParser);
+	CSIPMessage* sipMessage = CreateSIPMessageLC (preParser->FirstLineL());
+
+	TSIPHeaderNameValueIter iter (*preParser);
+	while (!iter.End())
+		{
+		CSIPHeaderNameValue* header = iter.NextL ();
+		RPointerArray<CSIPHeaderBase> headerArray;
+		TRAPD (err, headerArray = 
+			SIPHeaderLookup::CreateHeaderL(header->Name(),header->Value()));
+		delete header;
+		if (err == KErrNoMemory) 
+			{
+			User::Leave(KErrNoMemory);
+			}
+		if (err == KErrNone)
+			{
+			CSIPHeaderBase::PushLC(&headerArray);
+			for (TInt i=0; i < headerArray.Count(); i++)
+				{
+				sipMessage->AddHeaderL (headerArray[i]);
+				headerArray[i] = 0;
+				}
+			CleanupStack::PopAndDestroy(1); // headerArray
+			}
+		else // ignore header with syntax error
+			{
+			// Set the first error 
+			if (aParseErrorInHeaders == KErrNone) 
+				{
+				aParseErrorInHeaders = err;
+				}
+			}
+		}
+
+	HBufC8* content = preParser->ContentL();
+	sipMessage->SetContent (content);
+	CleanupStack::Pop(sipMessage);
+	CleanupStack::PopAndDestroy(preParser);
+	return sipMessage;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::CreateSIPMessageLC
+// -----------------------------------------------------------------------------
+//
+CSIPMessage* CSIPMessageParser::CreateSIPMessageLC (const TDesC8& aFirstLine)
+	{
+	CSIPMessage* sipMessage = NULL;
+
+	if (aFirstLine.FindF(KSIPWithSlash) == 0)
+		{
+		sipMessage = CreateSIPResponseLC(aFirstLine);
+		}
+	else
+		{
+		sipMessage = CreateSIPRequestLC(aFirstLine);
+		}
+
+	return sipMessage;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::CreateSIPRequestLC
+// -----------------------------------------------------------------------------
+//
+CSIPRequest* CSIPMessageParser::CreateSIPRequestLC (const TDesC8& aRequestLine)
+	{
+	__ASSERT_ALWAYS (aRequestLine.Length()>0, 
+	                 User::Leave(KErrSipCodecRequestLine));
+
+	//Method SP Request-URI SP SIP-Version
+	CSIPRequest* sipRequest = CSIPRequest::NewLC();
+	TLex8 lex(aRequestLine);
+
+	//Method
+	TPtrC8 method = lex.NextToken();
+	sipRequest->SetMethodL(method);
+
+    //Request-URI
+    CURIContainer* uri = CURIContainer::DecodeL(lex.NextToken());
+    CleanupStack::PushL(uri);
+    sipRequest->SetRequestURIL (uri);
+    CleanupStack::Pop(uri);
+
+	//SIP-Version
+	sipRequest->SetSIPVersionL(lex.NextToken());
+
+	return sipRequest;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::CreateSIPResponseLC
+// -----------------------------------------------------------------------------
+//
+CSIPResponse* CSIPMessageParser::CreateSIPResponseLC (const TDesC8& aStatusLine)
+	{
+	__ASSERT_ALWAYS (aStatusLine.Length()>0, 
+	                 User::Leave(KErrSipCodecResponseLine));
+
+	//SIP-Version SP Status-Code SP Reason-Phrase
+	CSIPResponse* sipResponse = CSIPResponse::NewL();
+	CleanupStack::PushL (sipResponse);
+	TLex8 lex(aStatusLine);
+
+	sipResponse->SetSIPVersionL (lex.NextToken());
+	sipResponse->SetResponseCodeL (ParseResponseCodeL(lex.NextToken()));
+	if (lex.Get() != ' ')
+		{
+		User::Leave(KErrSipCodecResponseLine);
+		}
+	sipResponse->SetReasonPhraseL (lex.Remainder());
+
+	return sipResponse;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPMessageParser::ParseResponseCodeL
+// -----------------------------------------------------------------------------
+//
+TUint CSIPMessageParser::ParseResponseCodeL (const TDesC8& aResponseCode)
+	{
+	__ASSERT_ALWAYS (aResponseCode.Length() > 0,
+					 User::Leave (KErrSipCodecResponseCode));
+
+	TLex8 lex(aResponseCode);
+	TUint chrCount=0;
+	lex.Mark();
+	TChar chr = lex.Get();
+	while (chr)
+		{
+		chrCount++;
+		chr = lex.Get();
+		}
+    const TInt KCharactersInResponseCode = 3;
+	if (chrCount != KCharactersInResponseCode) 
+		{
+		User::Leave (KErrSipCodecResponseCode);
+		}
+	lex.UnGetToMark();
+	TUint value=0;
+	if (lex.Val(value) != KErrNone) 
+		{
+		User::Leave (KErrSipCodecResponseCode);
+		}
+	return value;
+	}