upnp/upnpstack/upnphttptransfer/src/httpuploadworker.cpp
changeset 0 f5a58ecadc66
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies  this distribution, and is available 
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Handles upload of one file
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // User include files
       
    20 #include "httpuploadworker.h"
       
    21 
       
    22 // Constants
       
    23 _LIT8( KModuleName,         "HttpTransfer" );
       
    24 _LIT8( KAllowedData,        "*/*"          );
       
    25 _LIT8( KContentTypeName,    "Content-Type" );
       
    26 _LIT8( KDefaultContentType, "text/plain"   );
       
    27 _LIT8( KExpect,             "Expect" );
       
    28 _LIT8( K100Continue,        "100-continue" );
       
    29 
       
    30 const TUint KDefaultBufferSize = 64*KKilo;
       
    31 const TUint KMaxBufferSize     = 128*KKilo;
       
    32 
       
    33 // Time to wait for response after sending 100 continue post request.
       
    34 // Value in microseconds.
       
    35 const TInt K100ContinueResponseWaitTime = 3000000; // 3 seconds
       
    36 
       
    37 // ======== MEMBER FUNCTIONS ========
       
    38 
       
    39 // --------------------------------------------------------------------------
       
    40 // CHttpUploadWorker::CHttpUploadWorker()
       
    41 // (See comments in header file)
       
    42 // --------------------------------------------------------------------------
       
    43 //
       
    44 CHttpUploadWorker::CHttpUploadWorker( MHttpTransferObserver& aObserver,
       
    45                                       TUint /*aIAPId*/,
       
    46                                       TUint aBufferSize,
       
    47                                       MHttpWorkerObserver& aCallback )
       
    48     {
       
    49     iObserver = &aObserver;
       
    50     iCallback = &aCallback;
       
    51 
       
    52     iProcessState = EHttpTransactionIdle;
       
    53 
       
    54     // Check that size of the buffer is between boundaries
       
    55     if ( aBufferSize <= 0 )
       
    56         {
       
    57         iBufferSize = KDefaultBufferSize;
       
    58         }
       
    59     else if ( aBufferSize > KMaxBufferSize )
       
    60         {
       
    61         iBufferSize = KMaxBufferSize;
       
    62         }
       
    63     else
       
    64         {
       
    65         iBufferSize = aBufferSize;
       
    66         }
       
    67 
       
    68     iSendDataCount = 0;
       
    69     iBodyFileOffset = 0;
       
    70     iHttpStatus = 0;
       
    71     iMoreToCome = EFalse;
       
    72     iAlreadyDone = EFalse;
       
    73     }
       
    74 
       
    75 // --------------------------------------------------------------------------
       
    76 // CHttpUploadWorker::ConstructL()
       
    77 // (See comments in header file)
       
    78 // --------------------------------------------------------------------------
       
    79 //
       
    80 void CHttpUploadWorker::ConstructL()
       
    81     {
       
    82     CHttpTransferWorker::ConstructL();
       
    83     ConnectL();
       
    84     iSessionTimer = CHttpNotifyTimer::NewL( this );
       
    85     }
       
    86 
       
    87 // --------------------------------------------------------------------------
       
    88 // CHttpUploadWorker::NewL()
       
    89 // (See comments in header file)
       
    90 // --------------------------------------------------------------------------
       
    91 //
       
    92 CHttpUploadWorker* CHttpUploadWorker::NewL(
       
    93                                           MHttpTransferObserver& aObserver,
       
    94                                           TUint aIAPId,
       
    95                                           TUint aBufferSize,
       
    96                                           MHttpWorkerObserver& aCallback )
       
    97     {
       
    98     CHttpUploadWorker* self = CHttpUploadWorker::NewLC( aObserver,
       
    99                                                         aIAPId,
       
   100                                                         aBufferSize,
       
   101                                                         aCallback );
       
   102     CleanupStack::Pop( self );
       
   103     return self;
       
   104     }
       
   105 
       
   106 // --------------------------------------------------------------------------
       
   107 // CHttpUploadWorker::NewLC()
       
   108 // (See comments in header file)
       
   109 // --------------------------------------------------------------------------
       
   110 //
       
   111 CHttpUploadWorker* CHttpUploadWorker::NewLC(
       
   112                                           MHttpTransferObserver& aObserver,
       
   113                                           TUint aIAPId,
       
   114                                           TUint aBufferSize,
       
   115                                           MHttpWorkerObserver& aCallback )
       
   116     {
       
   117     CHttpUploadWorker* self = new( ELeave ) CHttpUploadWorker( aObserver,
       
   118                                                                aIAPId,
       
   119                                                                aBufferSize,
       
   120                                                                aCallback );
       
   121     CleanupStack::PushL( self );
       
   122     self->ConstructL();
       
   123     return self;
       
   124     }
       
   125 
       
   126 // --------------------------------------------------------------------------
       
   127 // CHttpUploadWorker::~CHttpUploadWorker()
       
   128 // (See comments in header file)
       
   129 // --------------------------------------------------------------------------
       
   130 //
       
   131 CHttpUploadWorker::~CHttpUploadWorker()
       
   132     {
       
   133     delete iRequestBodyBuffer;
       
   134     delete iSessionTimer;
       
   135     
       
   136     // Destroy the 100 continue timer if it exists.
       
   137     Destroy100ContinueTimer();
       
   138     }
       
   139 
       
   140 // --------------------------------------------------------------------------
       
   141 // CHttpUploadWorker::CancelTransfer()
       
   142 // (See comments in header file)
       
   143 // --------------------------------------------------------------------------
       
   144 //
       
   145 void CHttpUploadWorker::CancelTransfer()
       
   146     {
       
   147     iSessionTimer->Cancel();
       
   148 
       
   149     // Destroy the 100 continue response wait timer if it exists.
       
   150     Destroy100ContinueTimer();
       
   151     
       
   152     if ( iProcessState == EHttpWaitingForStart )
       
   153         {
       
   154         delete iProcessedFile;
       
   155         iProcessedFile = NULL;
       
   156         iProcessState = EHttpTransactionIdle;
       
   157         iCallback->WorkerCompleted();
       
   158         }
       
   159     // if process is finished do nothing
       
   160     else if ( iProcessState != EHttpTransactionIdle )
       
   161         {
       
   162         iHttpTransaction.Cancel(); 
       
   163 
       
   164         delete iRequestBodyBuffer;
       
   165         iRequestBodyBuffer = NULL;
       
   166 
       
   167         iProcessState = EHttpTransactionIdle;
       
   168         iHttpTransaction.Close();
       
   169 
       
   170         // call reset so that this worker can be used for the next download
       
   171         Reset(); 
       
   172 
       
   173         delete iProcessedFile;
       
   174         iProcessedFile = NULL;
       
   175 
       
   176         iOverallDataSize = 0;
       
   177         iFile.Close();
       
   178 
       
   179         // inform the worker observer
       
   180         iCallback->WorkerCompleted();
       
   181         }
       
   182     }
       
   183 
       
   184 // --------------------------------------------------------------------------
       
   185 // CHttpUploadWorker::MapPostTransactionError()
       
   186 // (See comments in header file)
       
   187 // --------------------------------------------------------------------------
       
   188 //
       
   189 TInt CHttpUploadWorker::MapPostTransactionError( TInt aError ) const
       
   190     {
       
   191     TInt error = KErrNone;
       
   192     switch (aError)
       
   193         {
       
   194         case HTTPStatus::EForbidden:
       
   195             {
       
   196             error = KErrAccessDenied;
       
   197             break;
       
   198             }
       
   199 
       
   200         case HTTPStatus::EMethodNotAllowed:
       
   201             {
       
   202             error = KErrAccessDenied;
       
   203             break;
       
   204             }
       
   205 
       
   206         case HTTPStatus::EConflict:
       
   207             {
       
   208             // resource already exists .
       
   209             error = KErrAlreadyExists;
       
   210             break;
       
   211             }
       
   212 
       
   213         case HTTPStatus::EUnsupportedMediaType:
       
   214             {
       
   215             error = KErrNotSupported;
       
   216             break;
       
   217             }
       
   218 
       
   219         case HTTPStatus::EInternalServerError:
       
   220             {
       
   221             error = KErrNotSupported;
       
   222             break;
       
   223             }
       
   224 
       
   225         case HTTPStatus::EMovedPermanently:
       
   226             {
       
   227             // fall through
       
   228             }
       
   229 
       
   230         case HTTPStatus::ETemporaryRedirect:
       
   231             {
       
   232             // It is not allowed to write a file with the same name
       
   233             // as an existing directory.
       
   234             error = KErrGeneral;    
       
   235             break;
       
   236             }
       
   237 
       
   238         default:
       
   239             {
       
   240             if ( HTTPStatus::IsServerError( aError ) )
       
   241                 {
       
   242                 error = KErrNotSupported;
       
   243                 }
       
   244             else if ( HTTPStatus::IsClientError( aError ) )
       
   245                 {
       
   246                 error = KErrAccessDenied;
       
   247                 }
       
   248             else if ( HTTPStatus::IsRedirection( aError ) )
       
   249                 {
       
   250                 error = KErrNotFound;
       
   251                 }
       
   252             else
       
   253                 {
       
   254                 if ( aError > 0 )
       
   255                     {
       
   256                     // An arbitrary choice for error codes that 
       
   257                     // should not occur
       
   258                     error = KErrAccessDenied;
       
   259                     }
       
   260                 }
       
   261             break;
       
   262             }
       
   263         }
       
   264 
       
   265     return error;
       
   266     }
       
   267 
       
   268 // --------------------------------------------------------------------------
       
   269 // CHttpUploadWorker::CompleteAndNotify()
       
   270 // (See comments in header file)
       
   271 // --------------------------------------------------------------------------
       
   272 //
       
   273 void CHttpUploadWorker::CompleteAndNotify( TInt aError )
       
   274     {
       
   275     iSessionTimer->Cancel();
       
   276         
       
   277     iProcessState = EHttpTransactionIdle;
       
   278     iHttpTransaction.Cancel();
       
   279     iHttpTransaction.Close();
       
   280 
       
   281     delete iRequestBodyBuffer;
       
   282     iRequestBodyBuffer = NULL;
       
   283 
       
   284     // call reset so that this worker can be used for the next download
       
   285     Reset(); 
       
   286     if ( iProcessedFile )
       
   287         {
       
   288         iObserver->TransferCompleted( iProcessedFile->Key(), aError );
       
   289         }
       
   290 
       
   291     delete iProcessedFile;
       
   292     iProcessedFile = NULL;
       
   293 
       
   294     iOverallDataSize = 0;
       
   295     iFile.Close();
       
   296 
       
   297     // inform the worker observer
       
   298     iCallback->WorkerCompleted();
       
   299     }
       
   300 
       
   301 // --------------------------------------------------------------------------
       
   302 // CHttpUploadWorker::StartProcessL()
       
   303 // (See comments in header file)
       
   304 // --------------------------------------------------------------------------
       
   305 //
       
   306 void CHttpUploadWorker::StartProcessL()
       
   307     {
       
   308     CHttpTransferWorker::StartProcessL();
       
   309     
       
   310     SendL();
       
   311     }
       
   312 
       
   313 // --------------------------------------------------------------------------
       
   314 // CHttpUploadWorker::SendL()
       
   315 // (See comments in header file)
       
   316 // --------------------------------------------------------------------------
       
   317 //
       
   318 void CHttpUploadWorker::SendL()
       
   319     {
       
   320     // iAlreadyDone need to be reset
       
   321     iSendDataCount = 0;
       
   322     iBodyFileOffset = 0;
       
   323     iHttpStatus = 0;
       
   324     iMoreToCome = EFalse;
       
   325     iAlreadyDone = EFalse;
       
   326     // Open the file in the file system
       
   327     User::LeaveIfError( iFile.Open( iFsSession,
       
   328                                     *(iProcessedFile->Path()),
       
   329                                     EFileShareReadersOnly | EFileRead ) );
       
   330 
       
   331     User::LeaveIfError( iFile.Size( iOverallDataSize ) );
       
   332 
       
   333     // get read buffer size from the Central Repository
       
   334     iRequestBodyBuffer = HBufC8::NewL( iBufferSize );
       
   335 
       
   336     InvokeHttpMethodL();
       
   337 
       
   338     // Change state of the state machine
       
   339     iProcessState = EHttpPostSent;
       
   340     }
       
   341 
       
   342 // --------------------------------------------------------------------------
       
   343 // CHttpUploadWorker::InvokeHttpMethodL()
       
   344 // (See comments in header file)
       
   345 // --------------------------------------------------------------------------
       
   346 //
       
   347 void CHttpUploadWorker::InvokeHttpMethodL()
       
   348     {
       
   349     // This actually creates the transaction, sets the headers and body 
       
   350     // and then starts the transaction.
       
   351     TBool contentTypeExists = EFalse;
       
   352 
       
   353     // open HTTP transaction
       
   354     TUriParser8 uri; 
       
   355     User::LeaveIfError( uri.Parse( *( iProcessedFile->Uri() ) ) );
       
   356 
       
   357     // POST HTTP method
       
   358     RStringF method = iStringPool.StringF( HTTP::EPOST,
       
   359                                            RHTTPSession::GetTable() );
       
   360     CleanupClosePushL( method );
       
   361 
       
   362     iHttpTransaction = iSession.OpenTransactionL( uri, *this, method );
       
   363 
       
   364     RHTTPHeaders hdr = iHttpTransaction.Request().GetHeaderCollection();
       
   365 
       
   366     SetHeaderL( hdr, HTTP::EUserAgent, KModuleName );
       
   367     SetHeaderL( hdr, HTTP::EAccept, KAllowedData );
       
   368 
       
   369     //Set the property of upnphttptransfer to ENotifyOnDisconnect
       
   370     //Set the property of HTTP Transaction to EEnableDisconnectNotification
       
   371     //The MHFRunL can get the really http error.
       
   372     iHttpTransaction.PropertySet().SetPropertyL(
       
   373         iSession.StringPool().StringF( 
       
   374             HTTP::ENotifyOnDisconnect,RHTTPSession::GetTable() ),
       
   375             iSession.StringPool().StringF( 
       
   376                 HTTP::EEnableDisconnectNotification,
       
   377                 RHTTPSession::GetTable() ) );
       
   378     // Add arbitrary Http headers
       
   379     RPointerArray<CHttpHeader> headerArray = iProcessedFile->Headers();
       
   380     TBool expect100ContinueFound = EFalse;
       
   381     for ( TInt i = 0; i < headerArray.Count(); i++ )
       
   382         {
       
   383         const TDesC8& headerName = headerArray[i]->FieldName();
       
   384         const TDesC8& headerValue = headerArray[i]->FieldValue();
       
   385         
       
   386         SetHeaderL( hdr,
       
   387                     headerName,
       
   388                     headerValue );
       
   389         if ( headerName == KContentTypeName() )
       
   390             {
       
   391             contentTypeExists = ETrue;
       
   392             }
       
   393         if ( headerName == KExpect() )
       
   394             {
       
   395             if ( headerValue == K100Continue() ) 
       
   396                 {
       
   397                 // Wait for 100 continue before sending the body in case of 
       
   398                 // "Expect: 100-Continue" header.
       
   399                 RHTTPTransactionPropertySet propSet = 
       
   400                     iHttpTransaction.PropertySet();
       
   401                 RStringF notifyContinue = 
       
   402                     iStringPool.StringF( 
       
   403                         HTTP::ENotify100Continue, 
       
   404                         RHTTPSession::GetTable() );
       
   405                 RStringF enableNotification = 
       
   406                     iStringPool.StringF( 
       
   407                         HTTP::EEnableNotification, 
       
   408                         RHTTPSession::GetTable() );
       
   409                 THTTPHdrVal val( enableNotification );
       
   410                 propSet.SetPropertyL( notifyContinue, val );
       
   411                       
       
   412                 // we found "Expect: 100-continue"-header
       
   413                 expect100ContinueFound = ETrue;
       
   414                 
       
   415                 // Need to start a timer when sending the headers that waits 
       
   416                 // for some time and if no response during that time, sends 
       
   417                 // this event to continue with the body.
       
   418                 i100ContinueTimer = CPeriodic::NewL( CActive::EPriorityStandard );
       
   419                 i100ContinueTimer->Start(
       
   420                     K100ContinueResponseWaitTime, // time to cancel waiting
       
   421                     K100ContinueResponseWaitTime, // this is not actually used
       
   422                     TCallBack( Cancel100ContinueWaitL, this ) );
       
   423                 }
       
   424             }
       
   425         }
       
   426 
       
   427     if ( contentTypeExists == EFalse )
       
   428         {
       
   429         SetHeaderL( hdr, HTTP::EContentType, KDefaultContentType );
       
   430         }
       
   431         
       
   432     if ( !expect100ContinueFound ) 
       
   433         {
       
   434         // "Expect: 100-continue" header not found. Do not wait for 
       
   435         // 100-continue. This might not be needed but it is added here to 
       
   436         // avoid possible regression by not changing the previous behaviour
       
   437         // too much. 
       
   438         RHTTPTransactionPropertySet propSet = iHttpTransaction.PropertySet();
       
   439         RStringF notifyContinue = 
       
   440             iStringPool.StringF( 
       
   441                 HTTP::ENotify100Continue, 
       
   442                 RHTTPSession::GetTable() );
       
   443         RStringF disableNotification = 
       
   444             iStringPool.StringF( 
       
   445                 HTTP::EDisableNotification, 
       
   446                 RHTTPSession::GetTable() );
       
   447         THTTPHdrVal val( disableNotification );
       
   448         propSet.SetPropertyL( notifyContinue, val );
       
   449         }
       
   450 
       
   451     // Set Body data
       
   452     MHTTPDataSupplier* dataSupplier = this;
       
   453     iHttpTransaction.Request().SetBody( *dataSupplier );
       
   454 
       
   455     // submit the request
       
   456     iHttpTransaction.SubmitL();
       
   457 
       
   458     //set timer
       
   459     iSessionTimer->Cancel();
       
   460     iSessionTimer->AfterSeconds( KSessionTimeout );
       
   461     CleanupStack::PopAndDestroy( &method );
       
   462     }
       
   463 
       
   464 // --------------------------------------------------------------------------
       
   465 // CHttpUploadWorker::MHFRunL()
       
   466 // (See comments in header file)
       
   467 // --------------------------------------------------------------------------
       
   468 void CHttpUploadWorker::MHFRunL( RHTTPTransaction aTransaction,
       
   469                                  const THTTPEvent& aEvent )
       
   470     {
       
   471     iSessionTimer->Cancel();
       
   472     
       
   473     // HTTP status code
       
   474     RHTTPResponse response = aTransaction.Response();
       
   475     iHttpStatus = response.StatusCode();
       
   476          
       
   477     // If HTTP status is not what we expected, better to quit
       
   478     // status 0 will be handled in switch case default
       
   479     
       
   480     if ( !( iHttpStatus == HTTPStatus::EOk ||
       
   481     	    iHttpStatus == HTTPStatus::ECreated ||
       
   482             iHttpStatus == HTTPStatus::ENoContent ||
       
   483             iHttpStatus == HTTPStatus::EContinue ||
       
   484             iHttpStatus == 0 ) )
       
   485         {
       
   486         CompleteAndNotify( 
       
   487                        MapPostTransactionError( iHttpStatus ) );
       
   488         }
       
   489     else
       
   490         {                
       
   491 
       
   492         switch ( aEvent.iStatus ) 
       
   493             {
       
   494             // process the headers
       
   495             case THTTPEvent::EGotResponseHeaders:
       
   496                 {
       
   497                 // POST response headers
       
   498                 // according to the RFC, location header is here if
       
   499                 // the entity was created
       
   500                 if( !iMoreToCome )
       
   501                     {
       
   502                     // Everything has been sent, no need to wait ESucceeded
       
   503                     
       
   504                     if ( ( iHttpStatus == HTTPStatus::EOk ) ||
       
   505                     	 ( iHttpStatus == HTTPStatus::ECreated ) ||
       
   506                          ( iHttpStatus == HTTPStatus::ENoContent ) )
       
   507                         {
       
   508                         CompleteAndNotify( KErrNone );
       
   509                         }
       
   510                      else
       
   511                         {
       
   512                         CompleteAndNotify( 
       
   513                            MapPostTransactionError( iHttpStatus ) );
       
   514                         }                            
       
   515                     }
       
   516                 break;
       
   517                 }
       
   518             case THTTPEvent::EGotResponseBodyData:
       
   519                 {
       
   520                 // discard the body data    
       
   521                 MHTTPDataSupplier* responseBody = 
       
   522                                     aTransaction.Response().Body();
       
   523                 ASSERT( responseBody );
       
   524                 // Done with that bit of body data
       
   525                 responseBody->ReleaseData();
       
   526                 break;
       
   527                 }
       
   528             case THTTPEvent::EResponseComplete:
       
   529                 {
       
   530                 // The transaction's response is complete
       
   531                 break;
       
   532                 }
       
   533             case THTTPEvent::ESucceeded:
       
   534                 {
       
   535                 // check the status code and decide whether we
       
   536                 // actually succeeded or not
       
   537 
       
   538                 // inform observers
       
   539                 // according to the RFC we expect 200 OK,
       
   540                 //                                204 NO CONTENT or
       
   541                 //                                201 CREATED    
       
   542                 if ( ( iHttpStatus == HTTPStatus::EOk ) ||
       
   543                 	 ( iHttpStatus == HTTPStatus::ECreated ) ||
       
   544                      ( iHttpStatus == HTTPStatus::ENoContent ) )
       
   545                     {
       
   546                     CompleteAndNotify( KErrNone );
       
   547                     }
       
   548                  else
       
   549                     {
       
   550                     CompleteAndNotify( 
       
   551                        MapPostTransactionError( iHttpStatus ) );
       
   552                     }
       
   553             	break;
       
   554                 }
       
   555             case THTTPEvent::EFailed:
       
   556             	{
       
   557             	// This is not supposed to do if transaction is finished
       
   558             	// happens when cancel is done
       
   559             	if ( iProcessState != EHttpTransactionIdle ) 
       
   560             	    {
       
   561             	    CompleteAndNotify( 
       
   562             	            MapPostTransactionError( iHttpStatus ) );
       
   563             	    }
       
   564 
       
   565                 break;
       
   566                 }
       
   567             case THTTPEvent::EReceived100Continue: 
       
   568                 {
       
   569                 // The server responded with a 100-Continue status code. 
       
   570                 // HTTP FW continues with sending the body.
       
   571                 Destroy100ContinueTimer();
       
   572                 break;
       
   573                 } 
       
   574             default:
       
   575                 {
       
   576                 if ( aEvent.iStatus < 0 )
       
   577                     {
       
   578                     CompleteAndNotify( aEvent.iStatus ); 
       
   579                     }
       
   580                 else
       
   581                     {
       
   582                     CompleteAndNotify( KErrGeneral );
       
   583                     }
       
   584                 break;
       
   585                 }
       
   586             }
       
   587         }
       
   588     }
       
   589 // --------------------------------------------------------------------------
       
   590 // CHttpUploadWorker::MHFRunError()
       
   591 // (See comments in header file)
       
   592 // --------------------------------------------------------------------------
       
   593 TInt CHttpUploadWorker::MHFRunError( TInt /*aError*/,
       
   594                                      RHTTPTransaction /*aTransaction*/,
       
   595                                      const THTTPEvent& /* aEvent*/ )
       
   596     {
       
   597     // Just notify the client about the failure and return KErrNone to 
       
   598     // the stack indicating that we handled this error.
       
   599     if ( iProcessState != EHttpTransactionIdle )
       
   600         {
       
   601         CompleteAndNotify( MapPostTransactionError( iHttpStatus ) );
       
   602         }
       
   603 
       
   604     return KErrNone;
       
   605     }
       
   606 
       
   607 // --------------------------------------------------------------------------
       
   608 // CHttpUploadWorker::GetNextDataPart()
       
   609 // (See comments in header file)
       
   610 // --------------------------------------------------------------------------
       
   611 //
       
   612 TBool CHttpUploadWorker::GetNextDataPart( TPtrC8& aDataPart )
       
   613     {
       
   614     if ( !iAlreadyDone )// Note: this is zero only when new part is requested
       
   615         {
       
   616         if ( iSendDataCount == 0 )
       
   617             {
       
   618             // first run
       
   619             TInt pos = iBodyFileOffset;
       
   620             iFile.Seek( ESeekStart, pos );
       
   621             }
       
   622 
       
   623         // We read data that will be given to the stack next time,
       
   624         // or we will find out that there is no more data...
       
   625         TInt readLength;
       
   626         if ( ( iOverallDataSize - iSendDataCount ) >= iBufferSize )
       
   627             {
       
   628             readLength = iBufferSize;
       
   629             }
       
   630         else
       
   631             {
       
   632             readLength = iOverallDataSize - iSendDataCount;
       
   633             }
       
   634 
       
   635         TPtr8 requestBodyBufferPtr = iRequestBodyBuffer->Des();
       
   636 
       
   637         TInt err = iFile.Read( requestBodyBufferPtr, readLength );
       
   638         iSendDataCount = iSendDataCount + iRequestBodyBuffer->Length();
       
   639         if ( err == KErrNone )
       
   640             {
       
   641             if ( ( iSendDataCount < iOverallDataSize ) &&
       
   642                  ( iRequestBodyBuffer->Length() > 0  ) )
       
   643                 {  
       
   644                 iMoreToCome = ETrue;
       
   645                 }
       
   646             }
       
   647         iAlreadyDone = ETrue;
       
   648         } // on first call, allocate the current part
       
   649 
       
   650     aDataPart.Set( *iRequestBodyBuffer ); // .. otherwise, just re-use it
       
   651 
       
   652     //set timer
       
   653     iSessionTimer->Cancel();
       
   654     iSessionTimer->AfterSeconds( KSessionTimeout );
       
   655 
       
   656     return !iMoreToCome;
       
   657     }
       
   658 
       
   659 // --------------------------------------------------------------------------
       
   660 // CHttpUploadWorker::ReleaseData()
       
   661 // (See comments in header file)
       
   662 // --------------------------------------------------------------------------
       
   663 //
       
   664 void CHttpUploadWorker::ReleaseData()
       
   665     {
       
   666     // HTTP client is ready with the current data
       
   667     // notify observer if notifications are required
       
   668     // and tell stack whether we have more data coming
       
   669     // when done, close file etc.
       
   670 
       
   671     // notify iObserver if iTrackProgress flag is on
       
   672     if ( iProcessedFile->TrackingOn() )
       
   673         {
       
   674         iObserver->TransferProgress( iProcessedFile->Key(),
       
   675                                      iSendDataCount,
       
   676                                      iOverallDataSize );
       
   677         }
       
   678 
       
   679     if ( iMoreToCome )
       
   680         {
       
   681         TRAP_IGNORE( iHttpTransaction.NotifyNewRequestBodyPartL() );
       
   682         iMoreToCome = EFalse;
       
   683         }
       
   684 
       
   685     iAlreadyDone = EFalse;
       
   686     }
       
   687 
       
   688 // --------------------------------------------------------------------------
       
   689 // CHttpUploadWorker::OverallDataSize()
       
   690 // (See comments in header file)
       
   691 // --------------------------------------------------------------------------
       
   692 //
       
   693 TInt CHttpUploadWorker::OverallDataSize()
       
   694     {
       
   695     return iOverallDataSize;
       
   696     }
       
   697 
       
   698 // --------------------------------------------------------------------------
       
   699 // CHttpUploadWorker::Reset()
       
   700 // (See comments in header file)
       
   701 // --------------------------------------------------------------------------
       
   702 //
       
   703 TInt CHttpUploadWorker::Reset()
       
   704     {
       
   705     // Reset send data count and buffer. This will cause GetNextDataPart() 
       
   706     // to start from the beginning.
       
   707     iSendDataCount = 0;
       
   708     
       
   709     // Destroy the 100 continue response wait timer if it exists.
       
   710     Destroy100ContinueTimer();
       
   711     
       
   712     return KErrNone;
       
   713     }
       
   714 
       
   715 // --------------------------------------------------------------------------
       
   716 // CHttpUploadWorker::Destroy100ContinueTimer()
       
   717 // (See comments in header file)
       
   718 // --------------------------------------------------------------------------
       
   719 // 
       
   720 void CHttpUploadWorker::Destroy100ContinueTimer() 
       
   721     {
       
   722     if ( i100ContinueTimer ) 
       
   723         {
       
   724         i100ContinueTimer->Cancel();
       
   725         delete i100ContinueTimer;
       
   726         i100ContinueTimer = NULL;
       
   727         }
       
   728     }
       
   729 
       
   730 // --------------------------------------------------------------------------
       
   731 // CHttpUploadWorker::Cancel100ContinueWaitL()
       
   732 // (See comments in header file)
       
   733 // --------------------------------------------------------------------------
       
   734 // 
       
   735 TInt CHttpUploadWorker::Cancel100ContinueWaitL( TAny* aParam ) 
       
   736     {
       
   737     CHttpUploadWorker* self =
       
   738         (static_cast<CHttpUploadWorker*>( aParam ));
       
   739 
       
   740     // Destroy the timer. We don't need subsequent events.
       
   741     self->Destroy100ContinueTimer(); 
       
   742 
       
   743     // Cancel waiting for 100 continue. As the server did not respond,
       
   744     // continue with sending the body.
       
   745     self->iHttpTransaction.SendEventL(
       
   746        THTTPEvent::ECancelWaitFor100Continue,
       
   747        THTTPEvent::EOutgoing,
       
   748        THTTPFilterHandle( THTTPFilterHandle::EClient) );
       
   749 
       
   750     return KErrNone;
       
   751     }
       
   752 
       
   753 // -----------------------------------------------------------------------------
       
   754 // CHttpUploadWorker::TimerEventL
       
   755 // Disconnect connection
       
   756 // -----------------------------------------------------------------------------
       
   757 //        
       
   758 void CHttpUploadWorker::TimerEventL( CHttpNotifyTimer* /*aTimer*/ )
       
   759     {
       
   760     CompleteAndNotify( KErrTimedOut );
       
   761     }
       
   762 
       
   763 // End of File