examples/ForumNokia/Symbian_OS_End-to-End_Sockets_API_Example/SocketTaskManager/engine/Response.cpp

00001 /*
00002  * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003  *    
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *    
00007  *  * Redistributions of source code must retain the above copyright notice, this
00008  *    list of conditions and the following disclaimer.
00009  *  * Redistributions in binary form must reproduce the above copyright notice,
00010  *    this list of conditions and the following disclaimer in the documentation
00011  *    and/or other materials provided with the distribution.
00012  *  * Neither the name of Nokia Corporation nor the names of its contributors
00013  *    may be used to endorse or promote products derived from this software
00014  *    without specific prior written permission.
00015  *    
00016  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  *    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022  *    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023  *    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024  *    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *    
00027  *    Description:  
00028  */
00029 
00030 
00031 // INCLUDE FILES
00032 #include "Response.h"
00033 #include "TaskManager.pan"
00034 
00035 // CONSTANTS
00036 _LIT(KError, "#Error:");
00037 _LIT(KOkMessage, "#OK");
00038 _LIT(KTab, "\t");
00039 _LIT(KSeparator, "#");
00040 
00041 // ================= MEMBER FUNCTIONS =======================
00042 
00043 // constructor
00044 CResponse::CResponse()
00045 : iMessageBuffer( NULL ), iExpectedPackageSize( 0 ), iState( ENotComplete )
00046         {
00047         }
00048         
00049 // destructor   
00050 CResponse::~CResponse()
00051         {
00052         iIds.Close();
00053         delete iDescriptions;
00054         delete iMessageBuffer;
00055         }
00056 
00057 // ----------------------------------------------------
00058 // CResponse::NewL()
00059 // Two-phased constructor.
00060 // ----------------------------------------------------
00061 //      
00062 CResponse* CResponse::NewL()
00063         {
00064         CResponse* self = CResponse::NewLC();
00065         CleanupStack::Pop(self);
00066         return self;
00067         }
00068 
00069 // ----------------------------------------------------
00070 // CResponse::NewLC()
00071 // Two-phased constructor.
00072 // ----------------------------------------------------
00073 //      
00074 CResponse* CResponse::NewLC()
00075         {
00076         CResponse* self = new (ELeave) CResponse;
00077         CleanupStack::PushL(self);
00078         self->ConstructL();
00079         return self;
00080         }
00081 
00082 // ----------------------------------------------------
00083 // CResponse::ConstructL()
00084 // Symbian OS default constructor can leave.
00085 // ----------------------------------------------------
00086 //      
00087 void CResponse::ConstructL()
00088         {
00089         iDescriptions = new (ELeave) CDesCArrayFlat(1);
00090     iMessageBuffer = HBufC::NewL(0);
00091         }
00092 
00093 // ----------------------------------------------------
00094 // CResponse::InputDataL()
00095 // This functions constructs a response object from the 
00096 // data received from the server. E.g. if aData contains 
00097 // tasks, tasks are parsed to arrays, where they can be 
00098 // easily fetched. 
00099 // ----------------------------------------------------
00100 //      
00101 void CResponse::ParseDataL( TDesC& aData )
00102         {
00103         // error occurred in the server side (i.e. the aData begins #Error: ).
00104         if (KError() == aData.Left(7))
00105                 {
00106                 iState = EError;
00107                 // remove the #-character.
00108                 iError = aData.Mid(1);
00109                 return;
00110                 }
00111         
00112         // response for completing task.
00113         if (aData.Find(KOkMessage) != KErrNotFound)
00114                 {
00115                 iResponseType = ETaskComplete;
00116                 return;
00117                 }
00118                 
00119         TLex lex(aData);
00120         TTaskReadStatus status = EStart;
00121         
00122         // Tasks are in form: #id#description#id#description#
00123         while (!lex.Eos())
00124                 {
00125                 if (lex.Peek() == TChar(KSeparator()[0]))
00126                         {
00127                         switch (status)
00128                                 {
00129                                 // first #-character found
00130                                 case EStart:
00131                                         {
00132                                         status = EReadId;
00133                                         break;
00134                                         }
00135                                 // read the id of the tasks.
00136                                 case EReadId:
00137                                         {
00138                                         status = EReadTask;
00139                                         TInt id;
00140                                         TLex tmp(lex.MarkedToken());
00141                                         User::LeaveIfError(tmp.Val(id));
00142                                         User::LeaveIfError(iIds.Append(id));
00143                                         break;
00144                                         }
00145                                 // read the description of the task.
00146                                 case EReadTask:
00147                                         {
00148                                         status = EReadId;
00149                                         TPtrC task = lex.MarkedToken();
00150                                         iDescriptions->AppendL(task);
00151                                         break;
00152                                         }
00153                                 }
00154                         lex.Inc();
00155                         lex.Mark();
00156                         }
00157                 else
00158                         {
00159                         lex.Inc();      
00160                         }
00161                 }       
00162         }
00163 
00164 // ----------------------------------------------------
00165 // CResponse::HasError()
00166 // Returns whether errors occurred in the server side 
00167 // or not.
00168 // ----------------------------------------------------
00169 //      
00170 TBool CResponse::HasError() const
00171         {
00172         TBool retval = EFalse;
00173         if (iError.Length() > 0)
00174                 {
00175                 retval = ETrue;
00176                 }
00177         return retval;
00178         }
00179 
00180 // ----------------------------------------------------
00181 // CResponse::Error()
00182 // Returns the error description. 
00183 // ----------------------------------------------------
00184 //      
00185 TBuf<KMaxError> CResponse::Error() const
00186         {
00187         return iError;
00188         }
00189 
00190 // ----------------------------------------------------
00191 // CResponse::TaskCount()
00192 // Returns the amount of tasks received from the server. 
00193 // ----------------------------------------------------
00194 //      
00195 TInt CResponse::TaskCount() const
00196         {
00197         return iIds.Count();
00198         }
00199 
00200 // ----------------------------------------------------
00201 // CResponse::TaskDescription()
00202 // Returns a task description. 
00203 // ----------------------------------------------------
00204 //      
00205 TBuf<KMaxTaskLength> CResponse::TaskDescription(const TInt& aIndex) const
00206         {
00207         if (aIndex >= iDescriptions->Count() || 0 > aIndex)
00208                 {
00209                 Panic(ETaskManagerInvalidTaskIndex);
00210                 }
00211                 
00212         return (*iDescriptions)[aIndex];
00213         }
00214 
00215 // ----------------------------------------------------
00216 // CResponse::TaskId()
00217 // Returns a task id. 
00218 // ----------------------------------------------------
00219 //      
00220 TInt CResponse::TaskId(const TInt& aIndex) const
00221         {
00222         if (aIndex >= iDescriptions->Count() || 0 > aIndex)
00223                 {
00224                 Panic(ETaskManagerInvalidTaskIndex);
00225                 }
00226 
00227         return iIds[aIndex];
00228         }
00229 
00230 // ----------------------------------------------------
00231 // CResponse::ResponseType()
00232 // Returns the type of this response. 
00233 // ----------------------------------------------------
00234 //      
00235 CResponse::TResponseType CResponse::ResponseType() const
00236         {
00237         return iResponseType;
00238         }
00239 
00240 // ----------------------------------------------------
00241 // CResponse::InputDataL()
00242 // Makes it possible to store a part of the data into the
00243 // CResponse class.
00244 // ----------------------------------------------------
00245 //      
00246 void CResponse::InputDataL( const TDesC8& aData )
00247     {
00248     iMessageBuffer = iMessageBuffer->ReAllocL(iMessageBuffer->Length() + aData.Length());
00249     HBufC* newData = HBufC::NewLC(aData.Length());
00250     newData->Des().Copy(aData);
00251     iMessageBuffer->Des() += newData->Des();
00252     CleanupStack::PopAndDestroy(newData);
00253     
00254     DoCheck();
00255     }
00256 
00257 // ----------------------------------------------------
00258 // CResponse::DoCheck()
00259 // Does a check on the received package and sets the state
00260 // that determines what the engine should do next.
00261 // ----------------------------------------------------
00262 //      
00263 void CResponse::DoCheck()
00264     {
00265         if( iExpectedPackageSize == 0 )
00266                 {
00267                 // We try to extract the size of the package, which should be found in the beginning
00268                 // of the package, before the first separator character
00269                 TInt separatorIndex = iMessageBuffer->Find( KSeparator );
00270 
00271                 if( separatorIndex == KErrNotFound )
00272                         { // The size of the package can't be read before the first separator sign is found
00273             iState = ENotComplete;
00274             return;
00275                         }
00276 
00277         // Extracted size is converted into TInt
00278                 TPtrC sizePtr = iMessageBuffer->Left( separatorIndex );
00279 
00280                 TLex converter( sizePtr );
00281                 if( converter.Val( iExpectedPackageSize ) != KErrNone )
00282                         { // conversion failed
00283             iState = EError;
00284             return;
00285                         }
00286                 }
00287 
00288     TBuf<6> asciiSize;
00289     asciiSize.Num( iExpectedPackageSize );
00290 
00291     if( iMessageBuffer->Length() - asciiSize.Length() < iExpectedPackageSize )
00292         { // The entire package hasn't been received
00293         iState = ENotComplete;
00294         return;
00295         }
00296 
00297     iExpectedPackageSize = 0;
00298 
00299     // The size component is cut from the message
00300     TPtrC data = iMessageBuffer->Right( iMessageBuffer->Length() -
00301                                         iMessageBuffer->Find( KSeparator ) );
00302     
00303         TRAPD(error, ParseDataL( data );)
00304         PanicIfError(error);
00305         
00306         iState = EComplete;
00307     }
00308 
00309 // ----------------------------------------------------
00310 // CResponse::GetState()
00311 // Returns the state to the engine.
00312 // ----------------------------------------------------
00313 //      
00314 CResponse::TResponseState CResponse::GetState() const
00315     {
00316     return iState;
00317     }
00318 
00319 // End of file

Generated by  doxygen 1.6.2