smsprotocols/smsstack/wapprot/Src/wapdgrm.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "gsmubuf.h"
       
    17 #include "gsmuset.h"
       
    18 #include "Gsmuelem.h"
       
    19 #include "Gsmumsg.h"
       
    20 #include "gsmusar.h"
       
    21 #include "gsmupdu.h"
       
    22 #include "WAPDGRM.H"
       
    23 #include "ws_main.h"
       
    24 #include "smsstackutils.h"
       
    25 
       
    26 //
       
    27 // For incoming short message
       
    28 //
       
    29 CWapDatagram* CWapDatagram::NewL(const CSmsMessage& aSms)
       
    30     {
       
    31     LOGWAPPROT2("CWapDatagram::NewL(): aSms=0x%08x", (TInt) &aSms);
       
    32 
       
    33     CWapDatagram* datagram = new (ELeave)CWapDatagram();
       
    34 
       
    35     CleanupStack::PushL(datagram);
       
    36     datagram->ConstructL(aSms);
       
    37     CleanupStack::Pop();
       
    38 
       
    39     LOGWAPPROT2("CWapDatagram::NewL(): iFromPort: %d", datagram->iFromPort);
       
    40     LOGWAPPROT2("CWapDatagram::NewL(): iToPort: %d", datagram->iToPort);
       
    41     LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
       
    42     LOGWAPPROT2("CWapDatagram::NewL(): iTotalSegments: %d", datagram->iTotalSegments);
       
    43     LOGWAPPROT2("CWapDatagram::NewL(): iSegmentNumber: %d", datagram->iSegmentNumber);
       
    44     LOGWAPPROT2("CWapDatagram::NewL(): iIsComplete: %d", datagram->iIsComplete);
       
    45     LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
       
    46     LOGWAPPROT2("CWapDatagram::NewL(): iIsTextHeader: %d", datagram->iIsTextHeader);
       
    47     LOGWAPPROT2("CWapDatagram::NewL(): iLogServerId: %d", datagram->iLogServerId);
       
    48     LOGWAPPROT2("CWapDatagram::NewL(): i16BitPorts: %d", datagram->i16BitPorts);
       
    49 
       
    50     // assert destination port
       
    51 	if (datagram->i16BitPorts)
       
    52 		{
       
    53 		if (datagram->iToPort>=0  &&  datagram->iToPort<=65535)
       
    54 			{
       
    55 			LOGWAPPROT1("iToPort OK");
       
    56 			}
       
    57 		else
       
    58 			{
       
    59 			LOGWAPPROT1("iToPort FAILED");
       
    60 			}
       
    61 		}
       
    62     else
       
    63 		{
       
    64         if (datagram->iToPort>=0  &&  datagram->iToPort<=255)
       
    65 			{
       
    66 		    LOGWAPPROT1("iToPort OK");
       
    67 			}
       
    68 		else
       
    69 			{
       
    70 			LOGWAPPROT1("iToPort FAILED");
       
    71 			}
       
    72 		}
       
    73 
       
    74 	if (datagram->i16BitPorts)
       
    75 		{
       
    76 		if (datagram->iFromPort>=0  &&  datagram->iFromPort<=65535)
       
    77 			{
       
    78 			LOGWAPPROT1("iFromPort OK");
       
    79 			}
       
    80 		else
       
    81 			{
       
    82 			LOGWAPPROT1("iFromPort FAILED");
       
    83 			}
       
    84 		}
       
    85     else
       
    86 		{
       
    87         if (datagram->iFromPort>=0  &&  datagram->iFromPort<=255)
       
    88 			{
       
    89 		    LOGWAPPROT1("iFromPort OK");
       
    90 			}
       
    91 		else
       
    92 			{
       
    93 			LOGWAPPROT1("iFromPort FAILED");
       
    94 			}
       
    95 		}
       
    96 
       
    97     return datagram;
       
    98     } // CWapDatagram::NewL
       
    99 
       
   100 
       
   101 //
       
   102 // For outgoing short messages
       
   103 //
       
   104 CWapDatagram* CWapDatagram::NewL(const TDesC8& aSendBuffer)
       
   105     {
       
   106     LOGWAPPROT2("CWapDatagram::NewL(): aSendBuffer=0x%08x", (TInt) &aSendBuffer);
       
   107 
       
   108     CWapDatagram* datagram = new (ELeave)CWapDatagram();
       
   109 
       
   110     CleanupStack::PushL(datagram);
       
   111     datagram->Construct(aSendBuffer);
       
   112     CleanupStack::Pop();
       
   113 
       
   114     return datagram;
       
   115     } // CWapDatagram::NewL
       
   116 
       
   117 
       
   118 CWapDatagram::~CWapDatagram()
       
   119     {
       
   120     LOGWAPPROT1("CWapDatagram::~CWapDatagram()");
       
   121 
       
   122 	delete iRecvbuf;
       
   123     delete iBuffer;
       
   124     delete iSegment;
       
   125     } // CWapDatagram::~CWapDatagram
       
   126 
       
   127 
       
   128 //
       
   129 // What about service centre address ?
       
   130 // aSmsMessageArray contains CSmsMessage objects
       
   131 //
       
   132 void CWapDatagram::EncodeConcatenatedMessagesL(RFs& aFs, CArrayPtr<CSmsMessage>& aSmsMessageArray)
       
   133     {
       
   134     LOGWAPPROT2("CWapDatagram::EncodeConcatenatedMessagesL(): %d messages", aSmsMessageArray.Count());
       
   135 
       
   136     // Couple of checkings makes sense
       
   137     __ASSERT_DEBUG(iToPort >=0 && iToAddress.Length()>=0
       
   138             && (iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet8Bit
       
   139                  || iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit),
       
   140             Panic(KPanicUsageError));
       
   141 
       
   142     // Determine CSmsMessage encoding by character width
       
   143     if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit)
       
   144         {
       
   145         CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
       
   146 
       
   147         CleanupStack::PushL(SmsBuffer);
       
   148         ConvertL(iSendBuffer,*SmsBuffer);
       
   149         CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
       
   150         CSmsMessage* SmsMessage = CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
       
   151         CleanupStack::PushL(SmsMessage);
       
   152         // one and only object
       
   153         aSmsMessageArray.AppendL(SmsMessage);
       
   154         CleanupStack::Pop(); // SmsMessage
       
   155 
       
   156         SetSmsMessageSettingsL(*SmsMessage,ETrue);
       
   157         }
       
   158     else
       
   159         {
       
   160         // contruct TWapTextMessage object
       
   161         TWapTextMessage* Segment = new (ELeave) TWapTextMessage(KNullDesC8);
       
   162         CleanupStack::PushL(Segment);
       
   163         CArrayPtrFlat<HBufC8>* SegmentArray = new (ELeave) CArrayPtrFlat<HBufC8> (8);
       
   164         CleanupStack::PushL(SegmentArray);
       
   165         CleanupResetAndDestroyPushL(*SegmentArray);
       
   166 
       
   167         Segment->SetDestinationPort(iToPort,i16BitPorts);
       
   168         Segment->SetSourcePort(iFromPort,i16BitPorts);
       
   169         Segment->SetReferenceNumber(iReference);
       
   170         Segment->SetUserData(iSendBuffer);
       
   171         Segment->SetOtherHeader(iOtherHeader);
       
   172         Segment->EncodeSegmentsL(*SegmentArray);
       
   173 
       
   174         // contruct array of CSmsMessages
       
   175         TInt Count = SegmentArray->Count();
       
   176         for (TInt i=0; i<Count; i++)
       
   177             {
       
   178             CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
       
   179 
       
   180             CleanupStack::PushL(SmsBuffer);
       
   181             ConvertL(*(SegmentArray->At(i)),*SmsBuffer);
       
   182             CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
       
   183             CSmsMessage* SmsMessage=CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
       
   184             CleanupStack::PushL(SmsMessage);
       
   185             aSmsMessageArray.AppendL(SmsMessage);
       
   186             CleanupStack::Pop(); // SmsMessage
       
   187 
       
   188             SetSmsMessageSettingsL(*SmsMessage,EFalse);
       
   189             }
       
   190         CleanupStack::PopAndDestroy(3, Segment);  // SegmentArray elements (Reset and Destroy), SegmentArray, Segment
       
   191 
       
   192         }
       
   193     } // CWapDatagram::EncodeConcatenatedMessagesL
       
   194 
       
   195 void CWapDatagram::DecodeConcatenatedMessagesL(CArrayPtr<TSegmentData>& aSmsMessageArray)
       
   196     {
       
   197     LOGWAPPROT1("CWapDatagram::DecodeConcatenatedMessagesL()");
       
   198 
       
   199     // The TSegmentData elements are in the random order in the array
       
   200     TInt Count = aSmsMessageArray.Count();
       
   201     TInt i=0;
       
   202 
       
   203     if (Count > 0)
       
   204         {
       
   205         TInt DataLength = 0;  // total length of data
       
   206         TInt TempLength = 0;
       
   207 
       
   208         // Every TSegmentData should be equal length except last segment
       
   209         // Use that 'constant' segment length as indexes
       
   210         // Count the actual data length
       
   211         for(i=0; i<Count; i++)
       
   212             {
       
   213             TempLength = aSmsMessageArray.At(i)->iData.Length();
       
   214             DataLength += TempLength;
       
   215             }
       
   216 
       
   217         TSegmentData* Segment = NULL;
       
   218 
       
   219         if (iBuffer)
       
   220             {
       
   221             delete iBuffer;
       
   222             iBuffer = NULL;
       
   223             }
       
   224         iBuffer = HBufC8::NewL(DataLength );
       
   225 
       
   226         TPtr8 BufferPtr(iBuffer->Des());
       
   227         BufferPtr.SetLength(DataLength );
       
   228 
       
   229         TInt segmentStartPosition=0;
       
   230 
       
   231         for(i=0; i<Count; i++)
       
   232             {
       
   233               if (segmentStartPosition >= DataLength)  
       
   234                   {
       
   235                   // Once the start position is out of range,
       
   236                   // there is no point in continuing reconstructing the
       
   237                   // wapdatagram.
       
   238                   break;
       
   239 				 }			
       
   240 			
       
   241             Segment = aSmsMessageArray.At(i);
       
   242 			TPtr8 CopyBufferPtr(&(BufferPtr[segmentStartPosition]),0,160);
       
   243 			CopyBufferPtr.Copy(Segment->iData);
       
   244  			segmentStartPosition+=Segment->iData.Length();
       
   245             }
       
   246         }
       
   247     iIsComplete = ETrue;
       
   248     } // CWapDatagram::DecodeConcatenatedMessagesL
       
   249 
       
   250 
       
   251 void CWapDatagram::InternalizeL(RReadStream& aStream)
       
   252     {
       
   253     aStream >> iUserDataSettings;
       
   254     aStream >> iToAddress;
       
   255     iToPort = aStream.ReadInt32L();
       
   256     aStream >> iFromAddress;
       
   257     iFromPort = aStream.ReadInt32L();
       
   258     TInt64 time;
       
   259     aStream >> time;
       
   260     iTime = time;
       
   261     iUTCOffset = aStream.ReadInt32L();
       
   262     iIsTextHeader = aStream.ReadInt32L();
       
   263     iReference = aStream.ReadInt32L();
       
   264     iTotalSegments = aStream.ReadInt32L();
       
   265     iSegmentNumber = aStream.ReadInt32L();
       
   266     iLogServerId = aStream.ReadInt32L();
       
   267     iVersionNumber = aStream.ReadInt32L();
       
   268     iSpare1 =  aStream.ReadInt32L();
       
   269     iSpare2 =  aStream.ReadInt32L();
       
   270     iSpare3 =  aStream.ReadInt32L();
       
   271 	
       
   272     // Required for version 1, which is reading and internalizing extra SMS parameters from stream
       
   273     if(iVersionNumber == EFirstVersion)
       
   274     	{
       
   275     	TInt length = aStream.ReadInt32L();
       
   276     	if(length>0)
       
   277     		{
       
   278     		HBufC8* smsBuffer=HBufC8::NewMaxLC(length);
       
   279 			TPtr8 recvbuftmp = smsBuffer->Des();
       
   280 			aStream >> recvbuftmp;
       
   281 			if(!iRecvbuf)
       
   282 				{
       
   283 				iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
       
   284 				}
       
   285 			iRecvbuf->ResizeL(recvbuftmp.Size());
       
   286 			iRecvbuf->Write(0, recvbuftmp);
       
   287 			CleanupStack::PopAndDestroy(smsBuffer);
       
   288 			}
       
   289     	}
       
   290     
       
   291     } // CWapDatagram::InternalizeL
       
   292 
       
   293 
       
   294 //
       
   295 //	Reads iBuffer from stream (for 8Bit messages)
       
   296 //
       
   297 void CWapDatagram::InternalizeBufferL(RReadStream& aStream)
       
   298 	{
       
   299 	TInt length;
       
   300 	length=aStream.ReadInt32L();
       
   301 	iBuffer=HBufC8::NewMaxL(length);
       
   302 	TPtr8 tmp = iBuffer->Des();
       
   303 	aStream >> tmp;
       
   304 	iIsComplete = ETrue;
       
   305 	}
       
   306 
       
   307 
       
   308 void CWapDatagram::ExternalizeL(RWriteStream& aStream) const
       
   309     {
       
   310     aStream << iUserDataSettings;
       
   311     aStream << iToAddress;
       
   312     aStream.WriteInt32L(iToPort);
       
   313 
       
   314     aStream << iFromAddress;
       
   315     aStream.WriteInt32L(iFromPort);
       
   316     aStream << iTime.Int64();
       
   317     aStream.WriteInt32L(iUTCOffset.Int());
       
   318 
       
   319     aStream.WriteInt32L(iIsTextHeader);
       
   320     aStream.WriteInt32L(iReference);
       
   321     aStream.WriteInt32L(iTotalSegments);
       
   322     aStream.WriteInt32L(iSegmentNumber);
       
   323 
       
   324     aStream.WriteInt32L(iLogServerId);
       
   325 
       
   326     aStream.WriteInt32L(iVersionNumber);
       
   327     aStream.WriteInt32L(iSpare1);
       
   328     aStream.WriteInt32L(iSpare2);
       
   329     aStream.WriteInt32L(iSpare3);
       
   330 	
       
   331 	// Externalizing the SMS params if exists
       
   332 	if(iRecvbuf)
       
   333 		{
       
   334 		TPtr8 recvbuftmp = iRecvbuf->Ptr(0);
       
   335 		aStream.WriteInt32L(recvbuftmp.Length());
       
   336 		aStream << recvbuftmp;
       
   337 		}
       
   338 	else
       
   339 		{
       
   340 		aStream.WriteInt32L(0);
       
   341 		}
       
   342     }
       
   343 
       
   344 
       
   345 //
       
   346 // writes iBuffer to writeStream for 8-bit incomming messages
       
   347 //
       
   348 void CWapDatagram::ExternalizeBufferL(RWriteStream& aStream) const
       
   349 	{
       
   350 	TInt length= WapDatagramLength();
       
   351 	aStream.WriteInt32L(length);
       
   352 	TPtr8 tmp= iBuffer->Des();
       
   353 	aStream << tmp;
       
   354 
       
   355 	} // CWapDatagram::ExternalizeBufferL
       
   356 
       
   357 
       
   358 //
       
   359 // Outgoing
       
   360 //
       
   361 void CWapDatagram::Construct(const TDesC8& aSendBuffer)
       
   362     {
       
   363     LOGWAPPROT1("CWapDatagram::Construct()");
       
   364 	
       
   365 	// Set version number to 1, as we have had to make 
       
   366 	// changes to CWapDatagram for CR0929
       
   367 	iVersionNumber = EFirstVersion;
       
   368 	
       
   369     iSendBuffer.Set(aSendBuffer);
       
   370     } // CWapDatagram::Construct
       
   371 
       
   372 
       
   373 //
       
   374 // Incoming
       
   375 // code actualy supports 7-bit characters and port numbers
       
   376 // encoded in information elements (IE) although it is not
       
   377 // a requirement
       
   378 //
       
   379 void CWapDatagram::ConstructL(const CSmsMessage& aSms)
       
   380     {
       
   381     LOGWAPPROT1("CWapDatagram::ConstructL()");
       
   382 
       
   383 	// Set version number to 1, as we have had to make 
       
   384 	// changes to CWapDatagram for CR0929
       
   385 	iVersionNumber = EFirstVersion;
       
   386 
       
   387 	iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
       
   388 
       
   389 	RBufWriteStream writestream(*iRecvbuf);
       
   390 	writestream.Open(*iRecvbuf);
       
   391 	CleanupClosePushL(writestream);
       
   392 	
       
   393 	// Externalizing everything within CSMSMessage except buffer
       
   394 	aSms.ExternalizeWithoutBufferL(writestream);
       
   395 	
       
   396 	CleanupStack::PopAndDestroy();  //  writestream
       
   397 
       
   398 	iRecvbuf->Compress();
       
   399 
       
   400     const CSmsBufferBase& SmsBufferBase = aSms.Buffer();
       
   401 
       
   402     GetDatagramSettings(aSms);
       
   403 
       
   404     // Get the data from CSmsMessage and convert
       
   405     // SmsBuffer store Unicode short message from CSmsMessage
       
   406     ConvertL(SmsBufferBase,&iBuffer);
       
   407 	GetDatagramSettingsL();
       
   408 
       
   409     iIsComplete = ETrue;
       
   410     if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit)
       
   411         {
       
   412         // this is a good candidate to include a text header.
       
   413         if (iIsTextHeader)
       
   414             {
       
   415             // there is still a minor chance that message is complete:
       
   416             // one fragment long datagram
       
   417             if (iTotalSegments == 1)
       
   418                 {
       
   419                 // Get the segment data
       
   420                 TPtr8 PtrNarrow = iBuffer->Des();
       
   421                 PtrNarrow.Zero();
       
   422                 iSegment->UserData(PtrNarrow);
       
   423                 }
       
   424             else
       
   425                 {
       
   426                 iIsComplete = EFalse;
       
   427                 // delete incomplete message from iBuffer;
       
   428                 delete iBuffer;
       
   429                 iBuffer = 0;
       
   430                 }
       
   431             }
       
   432         else
       
   433             // This means that IEs with 7-bits are used
       
   434             // Happily we support it
       
   435             // But what TODO if we are here due to an error, because
       
   436             // 7-bit with IEs should never happen ?
       
   437             iIsComplete = ETrue;
       
   438 
       
   439         }
       
   440     } // CWapDatagram::ConstructL
       
   441 
       
   442 
       
   443 //
       
   444 // Set WAP datagram private members from a text based concatenated message
       
   445 // Copies contents of iBuffer to iSmsBuffer
       
   446 // Allocates iSegment object
       
   447 //
       
   448 void CWapDatagram::GetDatagramSettingsL()
       
   449     {
       
   450     LOGWAPPROT1("CWapDatagram::GetDatagramSettingsL()");
       
   451 
       
   452 	/* The WAP stack always receives 8 bit WAP datagrams from the SMS Stack as a single CSmsMessage.
       
   453 	This is because 8 bit WAP messages which cannot be encoded into a single PDU are sent in a segmented SMS
       
   454 	message which is reassembled inside the SMS Stack; the SMS Stack always passes the WAP stack
       
   455 	a single CSmsMessage containing a single WAP message regardless of the message length.
       
   456 	The WAP stack can receive 7 Bit WAP datagrams either as a single CSmsMessage or as a number of CSmsMessages
       
   457 	which need to be reassembled into a single WAP message by the WAP stack.  The latter method is provided to maintain backward
       
   458 	compatibility with early versions of the WAP stack which were implemented before the concatenation function was
       
   459 	available in the SMS stack.*/
       
   460 
       
   461 	/* 160 is the maximum number of character that can be fitted in a single PDU using 7 bit encoding */
       
   462 	if((iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet8Bit) ||
       
   463 	(iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet7Bit && iBuffer->Length()>160 ))
       
   464 		{
       
   465 		iSegment = new (ELeave)TWapTextMessage(*iBuffer);
       
   466 		}
       
   467 	else if (iBuffer->Length()<=160)
       
   468         {
       
   469         iSmsBuffer = *iBuffer;
       
   470 		iSegment = new (ELeave)TWapTextMessage(iSmsBuffer);
       
   471         iIsTextHeader = iSegment->Parse();
       
   472 
       
   473         if (iIsTextHeader)
       
   474             {
       
   475             iFromPort = iSegment->SourcePort(&i16BitPorts);
       
   476             iToPort = iSegment->DestinationPort(&i16BitPorts);
       
   477             iReference = iSegment->ReferenceNumber();
       
   478             iTotalSegments = iSegment->TotalSegments();
       
   479             iSegmentNumber = iSegment->SegmentNumber();
       
   480             }
       
   481         }
       
   482 	else
       
   483 		{
       
   484         delete iSegment;
       
   485         iSegment = 0;
       
   486 		}
       
   487      } // CWapDatagram::GetDatagramSettingsL
       
   488 
       
   489 
       
   490 //
       
   491 // Set WAP datagram private members from information element structures
       
   492 //
       
   493 void CWapDatagram::GetDatagramSettings(const CSmsMessage& aSms)
       
   494     {
       
   495     LOGWAPPROT1("CWapDatagram::GetDatagramSettings()");
       
   496 
       
   497     const CSmsPDU& Pdu = aSms.SmsPDU();
       
   498 
       
   499     __ASSERT_DEBUG(Pdu.Type()==CSmsPDU::ESmsDeliver || Pdu.Type()==CSmsPDU::ESmsSubmit, // this line is testing purposes only
       
   500 			Panic(KPanicUsageError));
       
   501 
       
   502     aSms.UserDataSettings(iUserDataSettings);
       
   503 
       
   504     Pdu.ApplicationPortAddressing(iToPort,iFromPort,&i16BitPorts);
       
   505     if (iFromPort == (-1))
       
   506         iFromPort = iToPort;
       
   507 
       
   508     // From WAP datagram point of view following numbers are applicable
       
   509     iReference = 0;
       
   510     iTotalSegments = 1;
       
   511     iSegmentNumber = 1;
       
   512 
       
   513     iFromAddress = aSms.ToFromAddress();
       
   514     iToAddress = KNullDesC;
       
   515     iTime = aSms.Time();
       
   516 
       
   517     TBool result = SetUTCOffset(aSms.UTCOffset());
       
   518     __ASSERT_DEBUG(result, Panic(KPanicSmsMsgTimeZoneOutOfRange));
       
   519     } // CWapDatagram::GetDatagramSettings
       
   520 
       
   521 
       
   522 //
       
   523 // Set Alphabet information of iUserDataSettings before calling the method
       
   524 // Converts from 7/8-bit to UNICODE
       
   525 //
       
   526 void CWapDatagram::ConvertL(const TDesC8& aNarrowChars,CSmsBufferBase& aSmsBuffer) const
       
   527     {
       
   528     LOGWAPPROT1("CWapDatagram::ConvertL()");
       
   529 
       
   530 	// Convert the data in segments of specified max size
       
   531 	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
       
   532 
       
   533 	// Create converter and reassembler
       
   534 	RFs fs;
       
   535 	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
       
   536 	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
       
   537 	TSmsBufferReassembler reassembler(*converter,aSmsBuffer);
       
   538 
       
   539 	// Rassemble
       
   540 	TInt elementsRemaining=aNarrowChars.Length();
       
   541 	while (elementsRemaining)
       
   542 		{
       
   543 		TInt segmentLength=Min(KMaxSegmentSize,elementsRemaining);
       
   544 		TPtrC8 ptr(aNarrowChars.Ptr()+aNarrowChars.Length()-elementsRemaining,segmentLength);
       
   545 		reassembler.ReassembleNextL(ptr, ESmsEncodingNone,
       
   546 									elementsRemaining==segmentLength);
       
   547 		elementsRemaining-=segmentLength;
       
   548 		}
       
   549 
       
   550 	CleanupStack::PopAndDestroy(2);	// charConv,
       
   551     } // CWapDatagram::ConvertL
       
   552 
       
   553 
       
   554 //
       
   555 // Converts from UNICODE to 7/8-bit
       
   556 //
       
   557 void CWapDatagram::ConvertL(const CSmsBufferBase& aSmsBuffer,HBufC8** aNarrowChars) const
       
   558     {
       
   559     LOGWAPPROT1("CWapDatagram::ConvertL()");
       
   560 
       
   561 	// Convert the data in segments of specified max size
       
   562 	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
       
   563 
       
   564 	// Delete the existing buffer
       
   565 	if (*aNarrowChars)
       
   566 		{
       
   567 		delete *aNarrowChars;
       
   568 		*aNarrowChars=NULL;
       
   569 		}
       
   570 
       
   571 	// Create converter and segmenter
       
   572 	RFs fs;
       
   573 	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
       
   574 	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
       
   575 	CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aSmsBuffer,KMaxSegmentSize);
       
   576 
       
   577 	// Create a new buffer based on converted length
       
   578 	TInt convertedLength=segmenter->TotalConvertedLengthL(ESmsEncodingNone);
       
   579 	*aNarrowChars=HBufC8::NewMaxL(((convertedLength+KMaxSegmentSize-1)/KMaxSegmentSize)*KMaxSegmentSize);
       
   580 	TPtr8 narrowPtr=(*aNarrowChars)->Des();
       
   581 
       
   582 	// Now do the conversion
       
   583 	TInt elementsConverted=0;
       
   584 	TInt unconvertedChars=0;
       
   585 	TInt downgradedChars=0;
       
   586 	TBool complete=EFalse;
       
   587 	while (elementsConverted<convertedLength)
       
   588 		{
       
   589 		__ASSERT_DEBUG(elementsConverted<convertedLength,Panic(KPanicTooLongData));
       
   590 		TPtr8 ptr((TUint8*)narrowPtr.Ptr()+elementsConverted,0,KMaxSegmentSize);
       
   591 		complete=segmenter->SegmentNextL(ptr, unconvertedChars, downgradedChars, ESmsEncodingNone);
       
   592 		elementsConverted+=ptr.Length();
       
   593 		}
       
   594     if((!complete || (convertedLength!=elementsConverted)) &&  convertedLength)
       
   595         User::Leave( KErrCorrupt );
       
   596 	narrowPtr.SetLength(convertedLength);
       
   597 
       
   598 	CleanupStack::PopAndDestroy(3);	// charConv,converter,segmenter
       
   599     } // CWapDatagram::ConvertL
       
   600 
       
   601 
       
   602 void CWapDatagram::SetSmsMessageSettingsL(CSmsMessage& aSmsMessage, TBool aSetPorts)
       
   603     {
       
   604     LOGWAPPROT1("CWapDatagram::SetSmsMessageSettingsL()");
       
   605 
       
   606     CSmsPDU& Pdu = aSmsMessage.SmsPDU();
       
   607 
       
   608     aSmsMessage.SetToFromAddressL(iToAddress);
       
   609     aSmsMessage.SetUserDataSettingsL(iUserDataSettings);
       
   610     aSmsMessage.SetTime(iTime);
       
   611 
       
   612     TBool result = aSmsMessage.SetUTCOffset(iUTCOffset);
       
   613     __ASSERT_DEBUG(result, Panic(KPanicWapDgrmTimeZoneOutOfRange));
       
   614     
       
   615     if (aSetPorts)
       
   616         {
       
   617         if (iFromPort == (-1))
       
   618             iFromPort = iToPort;
       
   619 
       
   620         // Determine whether long or short form is used
       
   621         if (iFromPort > 255 || iToPort>255)
       
   622             i16BitPorts = ETrue;
       
   623 
       
   624 	    Pdu.SetApplicationPortAddressingL(ETrue,iToPort,iFromPort,i16BitPorts);
       
   625 		// WAP implementation guidelines recommend DCS of 0x15, however
       
   626 		// some gateways / SCs will only accept DCS 0xf5
       
   627 		Pdu.SetBits7To4(TSmsDataCodingScheme::ESmsDCSTextUncompressed7BitOr8Bit);
       
   628 		Pdu.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
       
   629 		Pdu.SetClass(ETrue,TSmsDataCodingScheme::ESmsClass1);
       
   630         }
       
   631     } // CWapDatagram::SetSmsMessageSettingsL
       
   632 
       
   633 
       
   634 CWapDatagram::CWapDatagram():
       
   635     iUserDataSettings(),
       
   636     iToAddress(KNullDesC),
       
   637     iFromAddress(KNullDesC),
       
   638     i16BitPorts(EFalse),
       
   639     iFromPort(-1),
       
   640     iToPort(-1),
       
   641     iTime(),
       
   642     iUTCOffset(0),
       
   643     iIsComplete(EFalse),
       
   644     iReference(0),
       
   645     iTotalSegments(0),
       
   646     iSegmentNumber(0),
       
   647     iIsTextHeader(EFalse),
       
   648     iSegment(NULL),
       
   649     iSmsBuffer(KNullDesC8),
       
   650     iBuffer(NULL),
       
   651     iSendBuffer(KNullDesC8),
       
   652     iOtherHeader(KNullDesC8),
       
   653     iLogServerId(0),
       
   654     iVersionNumber(EBaseVersion),// Set version number to EBaseVersion by default.
       
   655     iSpare1(0),
       
   656     iSpare2(0),
       
   657     iSpare3(0),
       
   658     iRecvbuf(NULL)
       
   659     {
       
   660     iTime.UniversalTime();
       
   661 
       
   662     TBool result = SetUTCOffset(User::UTCOffset());
       
   663    __ASSERT_DEBUG(result, Panic(KPanicUserSuppliedTimeZoneOutOfRange));
       
   664 
       
   665     iUserDataSettings.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
       
   666     __DECLARE_NAME(_S("CWapDatagram"));
       
   667     } // CWapDatagram::CWapDatagram
       
   668 
       
   669 
       
   670 //
       
   671 // Return the location of the link
       
   672 //
       
   673 TInt CWapDatagram::LinkOffset()
       
   674 	{
       
   675 	LOGWAPPROT1("CWapDatagram::LinkOffset()");
       
   676 
       
   677 
       
   678 	return _FOFF(CWapDatagram,iLink);
       
   679 	} // CWapDatagram::LinkOffset
       
   680 
       
   681 
       
   682 TBool CWapDatagram::SetUTCOffset(const TTimeIntervalSeconds& aUTCOffset)
       
   683     {
       
   684     LOGWAPPROT1("CWapDatagram::SetUTCOffset()");
       
   685 
       
   686     TBool rc = ETrue;
       
   687     TInt utcOffset = aUTCOffset.Int();
       
   688 
       
   689     if ((utcOffset <=  CSmsMessage::EMaximumSeconds) &&
       
   690         (utcOffset >= -CSmsMessage::EMaximumSeconds))
       
   691        {
       
   692        iUTCOffset = utcOffset;
       
   693        }
       
   694     else
       
   695        {
       
   696        LOGWAPPROT2("CWapDatagram:SetUTCOffset offset [out of range] = %d",utcOffset);
       
   697        rc = EFalse;
       
   698        }
       
   699 
       
   700     return rc;
       
   701     } // CWapDatagram::SetUTCOffset
       
   702     
       
   703 
       
   704 
       
   705 CBufFlat* CWapDatagram::SmsExternalisedStream() const
       
   706 	{
       
   707 	return iRecvbuf;
       
   708 	}