natfw/natfwunsaf_protocols/unsaf_codec/src/natfwunsafmessage.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/natfw/natfwunsaf_protocols/unsaf_codec/src/natfwunsafmessage.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,300 @@
+/*
+* Copyright (c) 2006-2007 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:   
+*
+*/
+
+
+
+
+#include <es_sock.h>
+#include "natfwunsafmessage.h"
+#include "natfwunsaftransactionid.h"
+#include "natfwunsafmessageintegrityattribute.h"
+#include "natfwunsaffingerprintattribute.h"
+#include "natfwunsafutils.h"
+
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::CNATFWUNSAFMessage
+// -----------------------------------------------------------------------------
+//
+CNATFWUNSAFMessage::CNATFWUNSAFMessage(
+    const TNATFWUNSAFTransactionID& aTransactionID)
+#ifdef TEST_EUNIT
+    : iAttributes(1)
+#endif
+    {
+    iTransactionID = aTransactionID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::~CNATFWUNSAFMessage
+// -----------------------------------------------------------------------------
+//
+CNATFWUNSAFMessage::~CNATFWUNSAFMessage()
+    {
+    iAttributes.ResetAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::TransactionID
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TNATFWUNSAFTransactionID CNATFWUNSAFMessage::TransactionID() const
+    {
+    return iTransactionID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::HasAttribute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CNATFWUNSAFMessage::HasAttribute(
+    CNATFWUNSAFAttribute::TType aType) const
+    {
+    return Attribute(aType) ? ETrue : EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::Attribute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CNATFWUNSAFAttribute* CNATFWUNSAFMessage::Attribute(
+    CNATFWUNSAFAttribute::TType aType) const
+    {
+    for (TInt i = 0; i < iAttributes.Count(); ++i)
+        {
+        if (iAttributes[i]->Type() == aType)
+            {
+            return iAttributes[i];
+            }
+        }
+
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::AddAttributeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CNATFWUNSAFMessage::AddAttributeL(
+    CNATFWUNSAFAttribute* aAttribute)
+    {
+    __ASSERT_ALWAYS(aAttribute, User::Leave(KErrArgument));
+
+    iAttributes.AppendL(aAttribute);
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::DetachAttribute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CNATFWUNSAFMessage::DetachAttribute(
+    const CNATFWUNSAFAttribute* aAttribute)
+    {
+    TInt pos = iAttributes.Find(aAttribute);
+    if (pos != KErrNotFound)
+        {
+        iAttributes.Remove(pos);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::DeleteAttribute
+// Start search from the end of the array, so that deleting an attribute doesn't
+// affect the positions of those attributes which haven't yet been checked.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CNATFWUNSAFMessage::DeleteAttribute(TUint16 aType)
+    {
+    for (TInt i = iAttributes.Count() - 1; i >= 0; --i)
+        {
+        if (iAttributes[i]->Type() == aType)
+            {
+            CNATFWUNSAFAttribute* attr = iAttributes[i];
+            DetachAttribute(attr);
+            delete attr;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::EncodeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CBufBase* CNATFWUNSAFMessage::EncodeL() const
+    {
+    CBufBase* msg = EncodeMessageHeaderLC();
+
+    for (TInt i = 0; i < iAttributes.Count(); ++i)
+        {
+        if (iAttributes[i]->Type() != CNATFWUNSAFAttribute::EMessageIntegrity &&
+            iAttributes[i]->Type() != CNATFWUNSAFAttribute::EFingerprint)
+            {
+            HBufC8* attribute = iAttributes[i]->EncodeL();
+            CleanupStack::PushL(attribute);
+            msg->InsertL(msg->Size(), *attribute);
+            CleanupStack::PopAndDestroy(attribute);
+            }
+        }
+    CleanupStack::Pop(msg);
+    msg->Compress();
+    SetMessageLength(*msg);
+
+    return msg;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::EncodeL
+// 1. Encode the UNSAF message normally.
+// 2. Create a MESSAGE-INTEGRITY attribute. This updates also the header's
+//    length field to include the MESSAGE-INTEGRITY before computing the hash.
+// 3. Encode it to the last attribute of the UNSAF message.
+// 4. Create a FINGERPRINT attribute. This updates also the header's
+//    length field to include the FINGERPRINT before computing the hash.
+// 5. Encode it to the last attribute of the UNSAF message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CBufBase* CNATFWUNSAFMessage::EncodeL(
+    const TDesC8& aSharedSecret,
+    TBool aUseFingerprint) const
+    {
+    CBufBase* msg = EncodeL();
+    CleanupStack::PushL(msg);
+    if ( aSharedSecret.Length() )
+        {
+        //Long term credentials need be used if there's a REALM attribute
+        CNATFWUNSAFMessageIntegrityAttribute* msgIntegrity =
+            CNATFWUNSAFMessageIntegrityAttribute::NewLC(aSharedSecret, *msg,
+                HasAttribute( CNATFWUNSAFAttribute::ERealm ));
+
+        HBufC8* encodedMsgIntegrity = msgIntegrity->EncodeL();
+        CleanupStack::PushL(encodedMsgIntegrity);
+        msg->InsertL(msg->Size(), *encodedMsgIntegrity);
+        CleanupStack::PopAndDestroy(encodedMsgIntegrity);
+        CleanupStack::PopAndDestroy(msgIntegrity);
+        }
+    if ( aUseFingerprint )
+        {
+        CNATFWUNSAFFingerprintAttribute* fingerprint =
+            CNATFWUNSAFFingerprintAttribute::NewLC(*msg);
+
+        HBufC8* encodedFingerprint = fingerprint->EncodeL();
+        CleanupStack::PushL(encodedFingerprint);
+        msg->InsertL(msg->Size(), *encodedFingerprint);
+        CleanupStack::PopAndDestroy(encodedFingerprint);
+        CleanupStack::PopAndDestroy(fingerprint); 
+        }
+
+    CleanupStack::Pop(msg);
+    msg->Compress();
+
+    return msg;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::UnknownMandatoryAttributeFound
+// -----------------------------------------------------------------------------
+//
+void CNATFWUNSAFMessage::UnknownMandatoryAttributeFound()
+    {
+    iUnknownMandatoryAttributes = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::HasUnknownMandatoryAttributes
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CNATFWUNSAFMessage::HasUnknownMandatoryAttributes() const
+    {
+    return iUnknownMandatoryAttributes;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::EncodeMessageHeaderLC
+// -----------------------------------------------------------------------------
+//
+CBufBase* CNATFWUNSAFMessage::EncodeMessageHeaderLC() const
+    {
+    CBufBase* header = CBufFlat::NewL(EHeaderSize);
+    CleanupStack::PushL(header);
+
+    TUint16 messageType = Type();
+    TUint16 bigEndianType(0);
+    BigEndian::Put16(reinterpret_cast<TUint8*>(&bigEndianType), messageType);
+    //First two bits of a STUN message are zero
+    bigEndianType = bigEndianType & EMessageTypeMask;
+    header->InsertL(EMessageTypeOffset, &bigEndianType, sizeof(bigEndianType));
+
+
+    TUint16 msgLength = 0;
+    //Value is zero, so it is same also in the big endian representation
+    header->InsertL(EMessageLengthOffset, &msgLength, sizeof(msgLength));
+
+    TUint32 bigEndianCookie(0);
+    BigEndian::Put32(reinterpret_cast<TUint8*>(&bigEndianCookie), EMagicCookie);
+    header->InsertL(EMagicCookieOffset,
+                    &bigEndianCookie,
+                    sizeof(bigEndianCookie));
+
+    header->InsertL(ETransactionIDOffset,
+                    iTransactionID,
+                    KMaxNATFWUNSAFTransactionIdLength);
+    return header;
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::MessageLength
+// TInt is guaranteed to be at least 32 bits.
+// -----------------------------------------------------------------------------
+//
+TInt CNATFWUNSAFMessage::MessageLength(const TDesC8& aNATFWUNSAFMessage)
+    {
+    if (aNATFWUNSAFMessage.Length() < EHeaderSize)
+        {
+        return KErrNotFound;
+        }
+
+    return BigEndian::Get16(aNATFWUNSAFMessage.Mid(EMessageLengthOffset).Ptr());
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::SetMessageLength
+// UNSAF message length does not include the NATFWUNSAF header
+// -----------------------------------------------------------------------------
+//
+void CNATFWUNSAFMessage::SetMessageLength(CBufBase& aNATFWUNSAFMessage)
+    {
+    SetMessageLength(aNATFWUNSAFMessage,
+        aNATFWUNSAFMessage.Size() - EHeaderSize);
+    }
+
+// -----------------------------------------------------------------------------
+// CNATFWUNSAFMessage::SetMessageLength
+// -----------------------------------------------------------------------------
+//
+void CNATFWUNSAFMessage::SetMessageLength(CBufBase& aNATFWUNSAFMessage,
+    TInt aLength)
+    {
+    __ASSERT_ALWAYS(aLength >= 0, User::Panic(KNullDesC, KErrUnderflow));
+
+    TUint16 bigEndianLength(0);
+    BigEndian::Put16(reinterpret_cast<TUint8*>(&bigEndianLength),
+                     static_cast<TUint16>(aLength));
+
+    aNATFWUNSAFMessage.Write(EMessageLengthOffset,
+                        &bigEndianLength,
+                        sizeof(bigEndianLength));
+    }