upnp/upnpstack/dlnawebserver/src/upnphttpsession.cpp
changeset 0 f5a58ecadc66
child 9 5c72fd91570d
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2  * Copyright (c) 2005-2006 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:  Declares HttpServer class.
       
    15  *
       
    16  */
       
    17 // INCLUDE FILES
       
    18 #include <in_sock.h>
       
    19 #include <e32std.h>
       
    20 #include <apgcli.h> // For RApaLsSession
       
    21 #include <apmstd.h>
       
    22 #include <escapeutils.h>
       
    23 #include <bautils.h>
       
    24 #include "upnphttpserver.h"
       
    25 #include "upnpstring.h"
       
    26 #include "upnpcons.h"
       
    27 #include "upnphttpsession.h"
       
    28 #include "upnphttpbuffer.h"
       
    29 #include "upnphttpfiletransferreader.h"
       
    30 #include "upnphttpfiletransferwriter.h"
       
    31 #include "upnphttpmessagefactory.h"
       
    32 #include "upnphttpheader.h"
       
    33 #include "upnperrors.h"
       
    34 #include "upnpcommonupnplits.h"
       
    35 #include "upnpfileutils.h"
       
    36 #define KLogFile _L("DLNAWebServer.txt")
       
    37 #include "upnpcustomlog.h"
       
    38 #include "upnphttpfileaccess.h"
       
    39 #include "httperr.h"
       
    40 #include "upnphttpservertransactioncreator.h"
       
    41 #include "upnprangeheaderparser.h"
       
    42 #include "upnphttpservertransaction.h"
       
    43 
       
    44 // CONSTANTS
       
    45 _LIT8( KTransferPending801, "HTTP/1.1 801 Transfer Pending");
       
    46 
       
    47 
       
    48 
       
    49 // ============================ MEMBER FUNCTIONS ===============================
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CUpnpHttpSession::NewL
       
    53 // Two-phased constructor
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 CUpnpHttpSession* CUpnpHttpSession::NewL( RSocket aSocket,
       
    57     CUpnpHttpServer* aServer, TInt aSessionId, TThreadPriority aPriority )
       
    58     {
       
    59     LOGS1(  "%i, CUpnpHttpSession::NewL - creating session for incoming connection",
       
    60             aSessionId );
       
    61 
       
    62     CUpnpHttpSession* self = new (ELeave) CUpnpHttpSession( aSocket, aServer,
       
    63         aSessionId, aPriority );
       
    64     CleanupStack::PushL( self );
       
    65     self->TcpConstructL( aSocket, KRcvBufSizeDefault,
       
    66         aServer->FileReadBufferSize() );
       
    67     self->ConstructL();
       
    68     CleanupStack::Pop( self );
       
    69 
       
    70     LOGS1( "%i, CUpnpHttpSession::NewL - HTTP *** Created new session.",
       
    71             self->Id( ) );
       
    72 
       
    73     return self;
       
    74     }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CUpnpHttpSession::CUpnpHttpSession
       
    78 // C++ default constructor
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 CUpnpHttpSession::CUpnpHttpSession( RSocket aSocket,
       
    82     CUpnpHttpServer* aServer, TInt aSessionId, TThreadPriority aPriority ) :
       
    83     CUpnpTcpSession( aSocket, aPriority )
       
    84     {
       
    85     iId = aSessionId;
       
    86     iServer = aServer;
       
    87     iRequestedTransferNotifySent = EFalse;
       
    88     // Assume that session should be kept alive unless the request
       
    89     // with HTTP header "Connection: close" comes.
       
    90     iSessionKeepAlive = ETrue;
       
    91     iSessionIsDeletedAfterResponse = EFalse;
       
    92     iUsesConnectionClose = EFalse;
       
    93     iSaveToFile = EFalse;
       
    94     iOverwriteExisting = EFalse;
       
    95     iOffset = 0;
       
    96     iLength = 0;
       
    97     iSaveAtOffset = EFalse;
       
    98     iMaximumSizeChecked = EFalse;
       
    99     iHeadersCompleted = EFalse;
       
   100     }
       
   101 
       
   102 // -----------------------------------------------------------------------------
       
   103 // CUpnpHttpSession::ConstructL
       
   104 // Two-phased constructor
       
   105 // -----------------------------------------------------------------------------
       
   106 //
       
   107 void CUpnpHttpSession::ConstructL()
       
   108     {
       
   109     LOGS1( "%i, CUpnpHttpSession::ConstructL", iId );
       
   110     iFileServe = NULL;
       
   111 
       
   112     iDestinationPath = HBufC8::NewL( 0 );
       
   113     iSenderPath = HBufC8::NewL( 0 );
       
   114 
       
   115     iInFilename = HBufC8::NewL( 0 );
       
   116     iOutFilename = HBufC8::NewL( 0 );
       
   117 
       
   118     iPendingRequests = new (ELeave) RPointerArray<CUpnpHttpMessage> ( 1 );
       
   119     }
       
   120 
       
   121 // -----------------------------------------------------------------------------
       
   122 // CUpnpHttpSession::~CUpnpHttpSession
       
   123 // C++ default destructor
       
   124 // -----------------------------------------------------------------------------
       
   125 //
       
   126 CUpnpHttpSession::~CUpnpHttpSession()
       
   127     {
       
   128     LOGS1( "%i, CUpnpHttpSession::~CUpnpHttpSession()", iId );
       
   129 
       
   130     delete iFileServe;
       
   131     delete iInFilename;
       
   132     delete iOutFilename;
       
   133     delete iDestinationPath;
       
   134     delete iSenderPath;
       
   135 
       
   136     if ( iPendingRequests )
       
   137         {
       
   138         iPendingRequests->ResetAndDestroy();
       
   139         iPendingRequests->Close();
       
   140         delete iPendingRequests;
       
   141         }
       
   142 
       
   143     // no deleting of iPendingRequest, it's not owned
       
   144     iPendingRequest = NULL;
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // CUpnpHttpSession::SendL
       
   149 // Send HTTP message.
       
   150 // -----------------------------------------------------------------------------
       
   151 //
       
   152 void CUpnpHttpSession::SendL( CUpnpHttpMessage* aMessage )
       
   153     {
       
   154     LOGS1( "%i, CUpnpHttpSession::SendL(CUpnpHttpMessage*)", iId );
       
   155 
       
   156     if ( !IsConnected() )
       
   157         {
       
   158         return;
       
   159         }
       
   160 
       
   161     iSessionNeedsErrorReply = EFalse;
       
   162 
       
   163     // Set senders and destination path
       
   164     delete iSenderPath;
       
   165     iSenderPath = NULL;
       
   166     delete iDestinationPath;
       
   167     iDestinationPath = NULL;
       
   168 
       
   169     if ( aMessage->Method().Find( KHttp11WithoutSpace ) == 0 )
       
   170         {
       
   171         iSenderPath = HBufC8::NewL( 0 );
       
   172         aMessage->AddPairL( UpnpHTTP::KHdrServer(),
       
   173             iServer->ServerDescription() );
       
   174         }
       
   175     else
       
   176         {
       
   177         iSenderPath = aMessage->SenderPathFromHeader().AllocL();
       
   178         }
       
   179 
       
   180     iDestinationPath = aMessage->SenderPath().AllocL();
       
   181 
       
   182     // Set other properties
       
   183     iRequestType = aMessage->Type();
       
   184     iRetryCounter = aMessage->RetryCounter();
       
   185 
       
   186     if ( aMessage->PendingRequest() )
       
   187         {
       
   188         iPendingRequest = aMessage->PendingRequest();
       
   189         }
       
   190 
       
   191     //we assume that converting to UTF8 is already done by upper layers
       
   192     HBufC8* buf = aMessage->ToStringL();
       
   193     CleanupStack::PushL( buf );
       
   194     WriteL( *buf );
       
   195     CleanupStack::PopAndDestroy( buf );
       
   196     if ( !iIsPersistent )
       
   197         {
       
   198         iSessionKeepAlive = EFalse;
       
   199         }
       
   200     }
       
   201 
       
   202 // -----------------------------------------------------------------------------
       
   203 // CUpnpHttpSession::DeleteThisSessionL
       
   204 // Delete the session.
       
   205 // -----------------------------------------------------------------------------
       
   206 //
       
   207 void CUpnpHttpSession::DeleteThisSessionL( CUpnpTcpSession* /*aSession*/)
       
   208     {
       
   209     LOGS1( "%i, CUpnpHttpSession::DeleteThisSessionL", iId );
       
   210 
       
   211     if ( iReceivedMessage )
       
   212         {
       
   213         if ( iReceivedMessage->BytesInBuffer() > 0
       
   214                 && iReceivedMessage->IsReadyL() )
       
   215             {
       
   216             TPtrC8 content = iReceivedMessage->Content();
       
   217             CUpnpHttpMessage* msg = CUpnpHttpMessage::NewL( content,
       
   218                 RemoteHost(), iId );
       
   219             CleanupStack::PushL( msg );
       
   220 
       
   221             msg->SetType( iRequestType );
       
   222 
       
   223             msg->SetRetryCounter( iRetryCounter );
       
   224 
       
   225             THttpInvalidMessage aVal;
       
   226             aVal = IsValidMessage( msg );
       
   227 
       
   228             switch ( aVal )
       
   229                 {
       
   230 
       
   231                 case EMessageOk:
       
   232                     //HandleQuery will take ownership of msg object
       
   233                     CleanupStack::Pop( msg );
       
   234                     // Pass the message forward
       
   235                     HandleQueryL( msg );
       
   236                     break;
       
   237 
       
   238                 default:
       
   239                     CleanupStack::PopAndDestroy( msg );
       
   240                     break;
       
   241                 }
       
   242             }
       
   243         }
       
   244 
       
   245     ShutdownStop();
       
   246 
       
   247     }
       
   248 
       
   249 // -----------------------------------------------------------------------------
       
   250 // CUpnpHttpSession::DeleteFileIfExists
       
   251 //
       
   252 // -----------------------------------------------------------------------------
       
   253 //
       
   254 void CUpnpHttpSession::DeleteFileIfExists( TDesC16& aFilename )
       
   255     {
       
   256     iServer->FileSession().Delete( aFilename );
       
   257     }
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 // CUpnpHttpSession::MatchHttpError
       
   261 //
       
   262 // -----------------------------------------------------------------------------
       
   263 //
       
   264 TInt CUpnpHttpSession::MatchHttpError( TInt error )
       
   265     {
       
   266     TInt httpError = KErrNone;
       
   267 
       
   268     if ( error == KErrDiskFull )
       
   269         httpError = EHttpInsufficientStorage;
       
   270     else if ( error == KErrOverflow ) //one of the reason can be if chunk value is > 2^32
       
   271         httpError = EHttpInsufficientStorage;
       
   272     else if ( error == KErrAbort ) //POST HTTP/1.1
       
   273         httpError = EHttpBadRequest;
       
   274     else if ( error == KErrGeneral || error == KErrHttpUnknownParseState ) // this error may occur e.g when ContentLengthL() leaves
       
   275         httpError = EHttpBadRequest;
       
   276     else if ( -error >= EHttpBadRequest ) // HTTP errors
       
   277         httpError = -error;
       
   278     else if ( error == KErrNoMemory )
       
   279         httpError = EHttpEntityTooLarge; // OOM handling
       
   280     else if ( error == KErrNotSupported )
       
   281         httpError = EHttpNotFound; // no transaction
       
   282     else
       
   283         httpError = EHttpInternalServerError;
       
   284 
       
   285     return httpError;
       
   286 
       
   287     }
       
   288 // -----------------------------------------------------------------------------
       
   289 // CUpnpHttpSession::BufferReceivedL
       
   290 //
       
   291 // -----------------------------------------------------------------------------
       
   292 //
       
   293 void CUpnpHttpSession::BufferReceivedL( TDesC8& aBuffer )
       
   294     {
       
   295 
       
   296     TInt index = 0;
       
   297     TPtrC8 ptrIn( aBuffer );
       
   298     iPendingPostRequests = ETrue;
       
   299     //handling requests on the server-side
       
   300     if ( ptrIn.Length() > KHttpPost().Length() )
       
   301         {
       
   302         TPtrC8 ptrInOffset( ptrIn.Mid( KHttpPost().Length() ) );
       
   303 
       
   304         //this loop splits buffer if it includes more than one POST message
       
   305         while ( (index = ptrInOffset.Find( KHttpPost() )) >= 0 )
       
   306             {
       
   307             TPtrC8 ptrL = ptrIn.Left( index + KHttpPost().Length() );
       
   308             SinglePostBufferReceivedL( ptrL );
       
   309             ptrIn.Set( ptrIn.Mid( index + KHttpPost().Length() ) );
       
   310             ptrInOffset.Set( ptrIn.Mid( KHttpPost().Length() ) );
       
   311             }
       
   312         }
       
   313     SinglePostBufferReceivedL( ptrIn );
       
   314     iPendingPostRequests = EFalse;
       
   315     }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CUpnpHttpSession::SinglePostBufferReceivedL
       
   319 //
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 void CUpnpHttpSession::SinglePostBufferReceivedL( TDesC8& aBuffer )
       
   323     {
       
   324     TInt error = KErrNone;
       
   325         TRAP( error, BufferReceivedProcessL( aBuffer ) )
       
   326     LOGS2( "%i, CUpnpHttpSession::BufferReceivedL finished with error %i", iId, error );
       
   327     if ( error != KErrNone )
       
   328         {
       
   329         //if session left - no continuation of file transfer
       
   330         if ( iFTReader && iFTReader->Activated() )
       
   331             {
       
   332             iFTReader->SetActivated( EFalse );
       
   333             if ( iFileServe )
       
   334                 iFileServe->DeleteFile();
       
   335             }
       
   336 
       
   337         TInt httpError = MatchHttpError( error );
       
   338         if ( httpError != KErrNone )
       
   339             {// If we act as a server side
       
   340             ResponseErrorL( httpError );
       
   341             if ( httpError == EHttpEntityTooLarge )
       
   342                 {
       
   343                 NotifyErrorL( httpError, error );
       
   344                 }
       
   345             ShutdownStop();
       
   346             return;
       
   347             }
       
   348         }
       
   349     }
       
   350 
       
   351 // -----------------------------------------------------------------------------
       
   352 // CUpnpHttpSession::BufferReceivedCheckingHeadersL
       
   353 //
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 void CUpnpHttpSession::BufferReceivedCheckingHeadersL( TDesC8& aBuffer )
       
   357     {
       
   358     // If iInFilename is defined, data should be saved in to a file,
       
   359     // this is the case of incoming GET response and for following parts of POST request.
       
   360     if ( iInFilename && iInFilename->Length() > 0 )
       
   361         {
       
   362         iSaveToFile = ETrue;
       
   363 
       
   364         // If this flag was set it means that even previously message was not ment
       
   365         // to be saved to file, now when the body is downloaded it will be saved to file.
       
   366         if ( iContinuedMessageDownload && !iReceivedMessage->IsToFile() )
       
   367             {
       
   368             iReceivedMessage->SetToFile( ETrue );
       
   369             }
       
   370 
       
   371         // Check Maximum Size requirement, but do this only once
       
   372         if ( !iMaximumSizeChecked )
       
   373             {
       
   374             //Make temp buffer to check content of incoming data,
       
   375             //its possible that content-Length is too huge (>2^32)
       
   376             CUpnpHttpBuffer* checkBuf = CUpnpHttpBuffer::NewL( this, EFalse );
       
   377             CleanupStack::PushL( checkBuf );
       
   378             //leaves in case of problems with string operation, no HTTP error
       
   379             checkBuf->AppendHeadersL( aBuffer, iSaveToFile );
       
   380 
       
   381             if ( checkBuf->IsHeaderReady() )
       
   382                 {
       
   383                 // Now headers were checked
       
   384                 iHeadersCompleted = ETrue;
       
   385                 TRAPD( error, checkBuf->ContentLengthL( ) );
       
   386                 if ( error )
       
   387                     {
       
   388                     iSaveToFile = EFalse;
       
   389                     }
       
   390                 iMaximumSizeChecked = ETrue;
       
   391 
       
   392                 //mark chunked encoding
       
   393                 iIsChunked = checkBuf->IsChunked();
       
   394                 //mark if persistent connection
       
   395                 if ( IsPersistentConnection() )
       
   396                     iIsPersistent = !checkBuf->UsesConnectionClose();
       
   397                 }
       
   398             else
       
   399                 {
       
   400                 iSaveToFile = EFalse;
       
   401                 }
       
   402 
       
   403             CleanupStack::PopAndDestroy( checkBuf );
       
   404             }
       
   405         }
       
   406     // Checking that if file is a POST that needs to be saved to a file. Only check this
       
   407     // for the first time (iFileServe does not exist only on receiving the first buffer of data)
       
   408     else if ( !iFileServe )
       
   409         {
       
   410         // making temp buffer to check content of incoming data
       
   411         CUpnpHttpBuffer* checkBuf = CUpnpHttpBuffer::NewL( this, EFalse );
       
   412         CleanupStack::PushL( checkBuf );
       
   413         //leaves in case of problems with string operation, no HTTP error
       
   414         checkBuf->AppendHeadersL( aBuffer, iSaveToFile );
       
   415 
       
   416         if ( checkBuf->IsHeaderReady() )
       
   417             {
       
   418             // Now headers were checked
       
   419             iHeadersCompleted = ETrue;
       
   420 
       
   421             TPtrC8 headers = checkBuf->Headers();
       
   422             CUpnpHttpMessage* tempMsg = NULL;
       
   423             TRAPD( err, tempMsg = CUpnpHttpMessage::NewL( (TDesC8&) headers,
       
   424                             RemoteHost( ), iId ) );
       
   425 
       
   426             //POST HTTP/1.1
       
   427             if ( err == KErrAbort )
       
   428                 {
       
   429                 if ( checkBuf->Method().Find( KHttpPost ) == 0 )
       
   430                     //leaves in case of HTTP error for a POST
       
   431                     User::Leave( KErrAbort );
       
   432                 }
       
   433             else if ( err < KErrNone )
       
   434                 {
       
   435                 User::Leave( err );
       
   436                 }
       
   437             else if ( err == KErrNone )
       
   438                 {
       
   439                 CleanupStack::PushL( tempMsg );
       
   440 
       
   441                 // Check method and make decision about handling message.
       
   442                 // It's a POST message
       
   443                 if ( tempMsg->Method().Find( KHttpPost ) == 0 )
       
   444                     {
       
   445                     // 100-Continue check should be done for all types of POST reqests, even for GENAs and SOAPs
       
   446 
       
   447                     // First thing to do in case of upload is to chceck if there
       
   448                     // is sufficient disk space to save incoming file.
       
   449                     TUint fileSize = 0;
       
   450                     TBool hasCL;
       
   451                     TLex8 cntLength( tempMsg->IsHeader(
       
   452                         UpnpHTTP::KHdrContentLength, hasCL ) );
       
   453                     if ( hasCL )
       
   454                         {
       
   455                         TInt errorLength = cntLength.Val( fileSize );
       
   456                         if ( errorLength == KErrOverflow )
       
   457                             {
       
   458                             iSaveToFile = EFalse;
       
   459                             //leaves in case of HTTP error
       
   460                             User::Leave( -EHttpInsufficientStorage );
       
   461                             }
       
   462                         else if ( errorLength != KErrNone )
       
   463                             {
       
   464                             iSaveToFile = EFalse;
       
   465                             //leaves in case of HTTP error
       
   466                             User::Leave( errorLength );
       
   467                             }
       
   468                         }
       
   469                     //First check URI, because there is no sense in sending 100 continue for invalid URI
       
   470                     if (!(tempMsg->IsGena()) && !(tempMsg->IsSoap()))
       
   471                         {
       
   472                         //response is sent inside function
       
   473 
       
   474                         delete iInFilename;
       
   475                         iInFilename = NULL;
       
   476                         
       
   477                         if ( !iServer->TransactionCreator() )
       
   478                             {
       
   479                             User::Leave( KErrNotSupported );
       
   480                             }
       
   481                         if ( UpnpFileUtil::ParseUri( tempMsg->SenderPathFromHeader() ) 
       
   482                              != KErrNone )
       
   483                             {
       
   484                             iInFilename = KNullDesC8().AllocL();
       
   485                             iSaveToFile = EFalse;
       
   486                             User::Leave( -EHttpBadRequest );
       
   487                             }
       
   488                         TPtrC8 relativeUri = PrepareRelativeUriL( tempMsg->SenderPathFromHeader() );
       
   489                         CUpnpHttpServerTransaction* transactionOut;
       
   490                         iServer->TransactionCreator()->NewTransactionL(
       
   491                                 tempMsg->Method(), relativeUri,
       
   492                                 tempMsg->Sender(), transactionOut );
       
   493                         CleanupStack::PushL( transactionOut );
       
   494 
       
   495                         transactionOut->SetRequest(tempMsg);
       
   496                         transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnRequestStart );
       
   497                         
       
   498                         iSaveToFile = EFalse;
       
   499                         User::LeaveIfError( transactionOut->Error() );
       
   500                         RBuf fileName;
       
   501                         fileName.CreateL( KMaxFileName );
       
   502                         CleanupClosePushL( fileName );
       
   503                         User::LeaveIfError( transactionOut->DataSink().FullName( fileName ) );
       
   504                         iInFilename = UpnpString::FromUnicodeL( fileName );
       
   505                         iSaveToFile = ETrue;
       
   506                         CleanupStack::PopAndDestroy(&fileName);
       
   507                         
       
   508                         transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnComplete );
       
   509                         CleanupStack::PopAndDestroy( transactionOut );
       
   510                         }
       
   511 
       
   512                     
       
   513                     //Maximum size was checked already so don't do this again
       
   514                     iMaximumSizeChecked = ETrue;
       
   515 
       
   516                     // If client sends Expect: 100-continue header then it must be checked
       
   517                     // if file can be saved and if so, server should responds with 100.
       
   518                     if ( tempMsg->GetHeaderValue( UpnpHTTP::KHdrExpect ).FindC(
       
   519                         UpnpHTTP::K100Continue ) == 0 )
       
   520                         {
       
   521 
       
   522                         // Check disk space and ContentLength limit (2^32) and if it's not sufficient send 507 response and
       
   523                         // close connection - sugested behaviour from DLNA 1.5 spec.
       
   524 
       
   525                         HBufC16* pathTmp = NULL;
       
   526                         pathTmp = UpnpString::ToUnicodeL( iInFilename->Des() );
       
   527                         CleanupStack::PushL( pathTmp );
       
   528 
       
   529                         TBool noSpace = UpnpFileUtil::CheckDiskSpaceShortL(
       
   530                             pathTmp->Des(), fileSize, iServer->FileSession() );
       
   531                         CleanupStack::PopAndDestroy( pathTmp );
       
   532 
       
   533                         if ( noSpace )
       
   534                             {
       
   535                             iSaveToFile = EFalse;
       
   536                             //leaves in case of HTTP error
       
   537                             User::Leave( -EHttpInsufficientStorage );
       
   538                             }
       
   539                         else
       
   540                             {
       
   541                             // Set the flag informing that current message's body will
       
   542                             // should be downloaded in some time
       
   543                             iContinuedMessageDownload = ETrue;
       
   544 
       
   545                             // If there is enough space to save incoming file send response 100,
       
   546                             // which means that client can continue with sending the body.
       
   547                             CUpnpHttpMessage* reply =
       
   548                                     RUpnpHttpMessageFactory::Http11ResponseL(
       
   549                                         tempMsg, EHttpContinue );
       
   550                             CleanupStack::PushL( reply );
       
   551                             HBufC8* sendBuf = reply->ToStringL();
       
   552                             CleanupStack::PushL( sendBuf );
       
   553                             WriteL( *sendBuf );
       
   554                             CleanupStack::PopAndDestroy( sendBuf );
       
   555                             CleanupStack::PopAndDestroy( reply );
       
   556                             }
       
   557 
       
   558                         }
       
   559                     }
       
   560                 if ( iSaveToFile )
       
   561                     {
       
   562                     CleanupStack::Pop( tempMsg );
       
   563                     tempMsg->SetType( ETransferStart );
       
   564                     iServer->ToReceiveStackD( tempMsg );
       
   565                     }
       
   566                 else
       
   567                     {
       
   568                     CleanupStack::PopAndDestroy( tempMsg );
       
   569                     }
       
   570                 }
       
   571             }
       
   572         //mark if chunked encoding
       
   573         iIsChunked = checkBuf->IsChunked();
       
   574         //mark if persistent connection
       
   575         if ( IsPersistentConnection() )
       
   576             iIsPersistent = !checkBuf->UsesConnectionClose();
       
   577         CleanupStack::PopAndDestroy( checkBuf );
       
   578         }
       
   579     else
       
   580         {
       
   581         iSaveToFile = EFalse;
       
   582         }
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 // CUpnpHttpSession::BufferReceivedProcessL
       
   587 //
       
   588 // -----------------------------------------------------------------------------
       
   589 //
       
   590 void CUpnpHttpSession::BufferReceivedProcessL( TDesC8& aBuffer )
       
   591     {
       
   592     TInt httpError;
       
   593     LOGS1( "%i, CUpnpHttpSession::BufferReceivedProcessL", iId );
       
   594 
       
   595     if ( !iHeadersCompleted && iReceivedMessage )
       
   596         {
       
   597         // If all headers aren't completed after receiving a few data chunks,
       
   598         // enlarge the buffer and try again.
       
   599         HBufC8* headers = HBufC8::NewLC( iReceivedMessage->Content().Length()
       
   600                 + aBuffer.Length() );
       
   601 
       
   602         headers->Des().Zero();
       
   603         headers->Des().Append( iReceivedMessage->Content() );
       
   604         headers->Des().Append( aBuffer );
       
   605         //returns HTTP error only in case of a POST
       
   606         BufferReceivedCheckingHeadersL( *headers );
       
   607         CleanupStack::PopAndDestroy( headers );
       
   608         }
       
   609     else if ( !iHeadersCompleted && !iReceivedMessage )
       
   610         {
       
   611         // The first data chunk, both variables are not set. returns HTTP error only in case of a POST
       
   612         BufferReceivedCheckingHeadersL( aBuffer );
       
   613         }
       
   614 
       
   615     // If message content should be saved to file then create a file access object
       
   616     // that takes care of this operation.
       
   617     if ( iSaveToFile && !iFileServe )
       
   618         {
       
   619         HBufC16* name = NULL;
       
   620         name = UpnpString::ToUnicodeL( *iInFilename );
       
   621         CleanupStack::PushL( name );
       
   622         iFileServe = CUpnpHttpFileAccess::NewL( this, *name );
       
   623         CleanupStack::PopAndDestroy( name );
       
   624 
       
   625         // If it's response for Range reqest then setup range saving parameters in iFileServe
       
   626         if ( iSaveAtOffset )
       
   627             {
       
   628             iFileServe->SetPosOfFile( iOffset );
       
   629             iFileServe->SetEndPosOfFile( iOffset + Length() - 1 );
       
   630             }
       
   631 
       
   632         delete iInFilename;
       
   633         iInFilename = NULL;
       
   634 
       
   635         iInFilename = UpnpString::FromUnicodeL( iFileServe->FileToServe() );
       
   636         }
       
   637     //initiate filetransfer component
       
   638     if ( iSaveToFile && iFileServe )
       
   639         {
       
   640         //file transfer reader
       
   641         iFileServe->SetEncodingMode( iIsChunked );
       
   642         FileTransferReaderConstructL();
       
   643         }
       
   644 
       
   645     if ( !iReceivedMessage )
       
   646         {
       
   647         iReceivedMessage = CUpnpHttpBuffer::NewL( this, iSaveToFile );
       
   648         }
       
   649     //leaves in case of problems with string operation, no HTTP error
       
   650     User::LeaveIfError( iReceivedMessage->AppendL( aBuffer, iSaveToFile ) );
       
   651 
       
   652     // This 'if statement' is required for proper deleting partial file
       
   653     // when 'stop transfer' was invoked during exporting the resource from other MS.
       
   654     if ( iFileServe && iReceivedMessage )
       
   655         iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
       
   656 
       
   657     
       
   658     if ( FileTransferReader() && FileTransferReader()->Activated() )
       
   659         return;
       
   660     // Finish receiving message and handle query contained in message.
       
   661     // Processing goes on and on till the incoming buffer is empty -
       
   662     // this is the way the pipelining is handled.
       
   663     while ( iReceivedMessage->IsReadyL() )
       
   664         {
       
   665 
       
   666         TPtrC8 buffer = iReceivedMessage->Content();
       
   667 
       
   668         CUpnpHttpMessage* msg = NULL;
       
   669         TInt err( KErrNone );
       
   670             TRAP( err, msg = CUpnpHttpMessage::NewL( buffer, RemoteHost( ), iId ) );
       
   671         CleanupStack::PushL( msg );
       
   672 
       
   673         if ( err < KErrNone )
       
   674             {
       
   675             LOGS1(
       
   676                     "%i, CUpnpHttpSession::BufferReceivedProcessL - failed", iId );
       
   677 
       
   678             // sending response to remote host: bad request
       
   679             httpError = MatchHttpError( -EHttpBadRequest );
       
   680             if ( httpError != KErrNone )
       
   681                 {// If we act as a server side
       
   682                 ResponseErrorL( httpError );
       
   683                 }
       
   684             CleanupStack::PopAndDestroy( msg );
       
   685             }
       
   686         else
       
   687             {
       
   688             iSessionKeepAlive = ETrue;
       
   689             if ( IsPersistentConnection() )
       
   690                 if ( !iFileServe && iPendingRequests->Count() == 0 )
       
   691                     if ( msg->GetHeaderValue( UpnpHTTP::KConnection() ).FindC(
       
   692                         UpnpHTTP::KClose() ) >= 0
       
   693                             || msg->RequestHTTPVersion() == KHttp10() )
       
   694                         {
       
   695                         iIsPersistent = EFalse;
       
   696                         }
       
   697 
       
   698             if ( !IsPersistentConnection() && !msg->IsSoap()
       
   699                     && !msg->IsGena() )
       
   700                 {
       
   701                 iSessionKeepAlive = EFalse;
       
   702                 }
       
   703 
       
   704             msg->SetType( iRequestType );
       
   705 
       
   706             msg->SetSessionId( iId );
       
   707 
       
   708             msg->SetRetryCounter( iRetryCounter );
       
   709 
       
   710             if ( (iSaveToFile) && (iInFilename) )
       
   711                 {
       
   712                 msg->SetInFilenameL( iInFilename->Des() );
       
   713                 }
       
   714 
       
   715             THttpInvalidMessage aVal;
       
   716             aVal = IsValidMessage( msg );
       
   717 
       
   718             switch ( aVal )
       
   719                 {
       
   720                 case EMessageOk:
       
   721                     //HandleQueryL will take ownership of msg object
       
   722                     CleanupStack::Pop( msg );
       
   723                     TRAP( err, HandleQueryL( msg ) );
       
   724                     if ( err < KErrNone ) 
       
   725                         {
       
   726                         httpError = MatchHttpError( err );
       
   727                         if ( httpError != KErrNone )
       
   728                             {// If we act as a server side
       
   729                             ResponseErrorL( httpError );
       
   730                             }
       
   731                         }
       
   732 
       
   733                     break;
       
   734 
       
   735                 case EUnknownMethod:
       
   736                     {
       
   737                     LOGS1H(
       
   738                             iHandle,
       
   739                             "%i, CUpnpHttpSession::BufferReceivedL - Unknown method",
       
   740                             iId );
       
   741 
       
   742                     httpError = MatchHttpError( -EHttpMethodNotAllowed );
       
   743                     if ( httpError != KErrNone )
       
   744                         {// If we act as a server side
       
   745                         ResponseErrorL( httpError );
       
   746                         }
       
   747                     CleanupStack::PopAndDestroy( msg );
       
   748                     }
       
   749                     break;
       
   750 
       
   751                 default:
       
   752                     LOGS1(
       
   753                             "%i, CUpnpHttpSession::BufferReceivedL - failed", iId );
       
   754                     CleanupStack::PopAndDestroy( msg );
       
   755                     break;
       
   756                 };
       
   757 
       
   758             }
       
   759 
       
   760         // No continued message download is expected because
       
   761         // the message processing is finished
       
   762         iContinuedMessageDownload = EFalse;
       
   763         iReceivedMessage->RemoveL( buffer.Length() );
       
   764 
       
   765         iHeadersCompleted = EFalse;
       
   766 
       
   767         delete iInFilename;
       
   768         iInFilename = NULL;
       
   769         iInFilename = HBufC8::NewL( 0 );
       
   770 
       
   771         if ( iSessionIsDeletedAfterResponse )
       
   772             {
       
   773             StartDisconnect();
       
   774             }
       
   775         }
       
   776 
       
   777     if ( iReceivedMessage->BytesInBuffer() <= 0 )
       
   778         {
       
   779         delete iReceivedMessage;
       
   780         iReceivedMessage = NULL;
       
   781         if ( iSessionIsDeletedAfterResponse )
       
   782             {
       
   783             StartDisconnect();
       
   784             }
       
   785         else
       
   786             {
       
   787             StartTimeoutTimer( iSessionNeedsErrorReply );
       
   788             }
       
   789         }
       
   790     }
       
   791 
       
   792 // -----------------------------------------------------------------------------
       
   793 // CUpnpHttpSession::ResponseErrorL
       
   794 //
       
   795 // -----------------------------------------------------------------------------
       
   796 //
       
   797 void CUpnpHttpSession::ResponseErrorL( TInt aStatus )
       
   798     {
       
   799     LOGS2( "%i, CUpnpHttpSession::ResponseErrorL - error code %i",
       
   800             iId, aStatus );
       
   801 
       
   802     CUpnpHttpMessage* reply = NULL;
       
   803     reply = RUpnpHttpMessageFactory::HttpResponseErrorL( RemoteHost(),
       
   804         aStatus );
       
   805     CleanupStack::PushL( reply );
       
   806 
       
   807     reply->AddPairL( UpnpHTTP::KHdrServer(), iServer->ServerDescription() );
       
   808     reply->SetSessionId( Id() );
       
   809     reply->SetDestinationPathL( *iDestinationPath );
       
   810     reply->SetSenderPathL( *iSenderPath );
       
   811 
       
   812     HBufC8* sendBuf = reply->ToStringL();
       
   813     CleanupStack::PushL( sendBuf );
       
   814     WriteL( *sendBuf );
       
   815     CleanupStack::PopAndDestroy( sendBuf );
       
   816     CleanupStack::PopAndDestroy( reply );
       
   817     }
       
   818 // -----------------------------------------------------------------------------
       
   819 // CUpnpHttpSession::HandleQueryL
       
   820 //
       
   821 // -----------------------------------------------------------------------------
       
   822 //
       
   823 void CUpnpHttpSession::HandleQueryL( CUpnpHttpMessage* aMsg )
       
   824     {
       
   825     LOGS1( "%i, CUpnpHttpSession::HandleQueryL", iId );
       
   826     CleanupStack::PushL( aMsg );
       
   827     
       
   828     // Handle GET and HEAD requests
       
   829     if ( aMsg->Method().Find( KHttpGet ) == 0 || aMsg->Method().Find(
       
   830         KHttpHead ) == 0 )
       
   831         {
       
   832         // method starts with GET or HEAD
       
   833         if ( FileServeExists() || (FileTransferWriter()
       
   834                 && FileTransferWriter()->IsActive()) )
       
   835             {
       
   836             User::LeaveIfError( iPendingRequests->Append( aMsg ) );
       
   837             CleanupStack::Pop( aMsg );
       
   838             }
       
   839         else
       
   840             {
       
   841             User::LeaveIfError( PrepareToServeFileL( aMsg ) );
       
   842             CleanupStack::PopAndDestroy( aMsg );
       
   843             aMsg = NULL;
       
   844             }
       
   845         }
       
   846 
       
   847     // Handle GENA, SOAP, responses, other messages etc.
       
   848     else
       
   849         {
       
   850         aMsg->SetInFilenameL( *iInFilename );
       
   851         delete iInFilename;
       
   852         iInFilename = NULL;
       
   853         iInFilename = HBufC8::NewL( 0 );
       
   854         if ( !aMsg->Is1xx() )
       
   855             {
       
   856             CleanupStack::Pop( aMsg );
       
   857             NotifyUpperLayerLD( aMsg );
       
   858             iPendingRequest = NULL;
       
   859             }
       
   860         else
       
   861             {
       
   862             CleanupStack::PopAndDestroy( aMsg );
       
   863             }
       
   864         }
       
   865     }
       
   866 
       
   867 // -----------------------------------------------------------------------------
       
   868 // CUpnpHttpSession::PrepareToServeFileL
       
   869 //
       
   870 // -----------------------------------------------------------------------------
       
   871 //
       
   872 TInt CUpnpHttpSession::PrepareToServeFileL( CUpnpHttpMessage* aMsg )
       
   873     {
       
   874 
       
   875     LOGS1( "%i, CUpnpHttpSession::PrepareToServeFileL", iId );
       
   876     if ( !iServer->TransactionCreator() )
       
   877          {
       
   878          User::Leave( KErrNotSupported ); 
       
   879          }
       
   880     
       
   881     CheckSessionPersistence( aMsg );
       
   882     TInt parseUrlError = UpnpFileUtil::ParseUri( aMsg->SenderPathFromHeader() );
       
   883     if ( parseUrlError != KErrNone )
       
   884         {
       
   885         return -EHttpBadRequest;
       
   886         }
       
   887     
       
   888     TPtrC8 relativeUri = PrepareRelativeUriL( aMsg->SenderPathFromHeader() );
       
   889     
       
   890     CUpnpHttpServerTransaction* transactionOut; 
       
   891     iServer->TransactionCreator()->NewTransactionL( aMsg->Method() ,
       
   892             relativeUri, aMsg->Sender(), transactionOut );    
       
   893     CleanupStack::PushL( transactionOut );
       
   894     
       
   895     transactionOut->SetRequest( aMsg );    
       
   896     transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnRequestStart );
       
   897     TInt error = transactionOut->Error();
       
   898     if( error != KErrNone )
       
   899         {
       
   900         CleanupStack::PopAndDestroy( transactionOut ); 
       
   901         return error;
       
   902         }
       
   903                  
       
   904     // 2. Try to open requested file
       
   905     RFile& file = transactionOut->DataSource();
       
   906     
       
   907     TInt fileSize = -1;    
       
   908     if( file.Size( fileSize ) != KErrNone  )
       
   909         {
       
   910         fileSize = -1;
       
   911         }
       
   912 
       
   913     TBool servingOutFilename = ( aMsg->OutFilename().Length() > 0 );
       
   914 
       
   915     TInt result( KErrNone );
       
   916     // 3. If file was opened it means it exists and might be served
       
   917     if ( fileSize >= 0 )
       
   918         {
       
   919         TInt rangeStatus;
       
   920         TInt startPos;
       
   921         TInt endPos;
       
   922         TInt errorValue;
       
   923         errorValue = PrepareRangeHeaderL( 
       
   924             aMsg, servingOutFilename, fileSize, *transactionOut,
       
   925             rangeStatus, startPos, endPos );
       
   926         
       
   927         if ( errorValue == KErrNone )
       
   928             {
       
   929             if ( EHttpNoContent == rangeStatus )
       
   930                 {
       
   931                 transactionOut->AddResponseHeaderL( UpnpHTTP::KHdrServer(),
       
   932                                                     iServer->ServerDescription() );             
       
   933              
       
   934                 WriteL( transactionOut->QueryResponseHeader() );
       
   935                 }
       
   936             else
       
   937                 {
       
   938                 transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnResponseStart );
       
   939                 //last header fiished by double CRLF so we must add last CRLF
       
   940 
       
   941                 errorValue = transactionOut->Error();
       
   942                 if ( errorValue != KErrNone  ) 
       
   943                     {
       
   944                         CleanupStack::PopAndDestroy( transactionOut );
       
   945                         return errorValue;
       
   946                     }
       
   947                 if ( transactionOut->QueryResponseHeader().Length() > 0 )
       
   948                     {
       
   949                     transactionOut->AddResponseHeaderL( UpnpHTTP::KHdrServer(),
       
   950                                                         iServer->ServerDescription() );             
       
   951                     RBuf fileName;
       
   952                     fileName.CreateL( KMaxFileName );
       
   953                     CleanupClosePushL( fileName );
       
   954                     User::LeaveIfError( file.FullName( fileName ) );
       
   955                     WriteMsgAndHeaderL( aMsg, transactionOut->QueryResponseHeader(),
       
   956                         fileName, fileSize, rangeStatus, startPos, endPos );
       
   957                     CleanupStack::PopAndDestroy( &fileName );
       
   958                     }
       
   959                 }
       
   960             }
       
   961         result = errorValue;
       
   962         }
       
   963     else // 4. File was not found, so just respose with HTTP 404 error.
       
   964         {
       
   965 
       
   966         if ( !iSaveToFile )
       
   967             {
       
   968             //error. No such file or folder found. Send error message.
       
   969             result = -EHttpNotFound;
       
   970             }
       
   971         }
       
   972     if ( KErrNone == result )
       
   973         {
       
   974         result = transactionOut->Error();
       
   975         }    
       
   976 
       
   977     
       
   978     transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnComplete );
       
   979     CleanupStack::PopAndDestroy( transactionOut );
       
   980     return result;
       
   981     }
       
   982 
       
   983 // -----------------------------------------------------------------------------
       
   984 // CUpnpHttpSession::WriteMsgAndHeaderL
       
   985 //
       
   986 // -----------------------------------------------------------------------------
       
   987 //
       
   988 void CUpnpHttpSession::WriteMsgAndHeaderL( CUpnpHttpMessage* aMsg,
       
   989     const TDesC8& aHeaderToWrite, const TDesC& aPathWithNewMethod,
       
   990     TInt aFileSize, TInt aRangeStatus, const TInt aStartPos,
       
   991     const TInt aEndPos )
       
   992     {
       
   993     if ( aMsg->Method().Find( KHttpHead ) == 0 ) // HEAD - just header
       
   994         {
       
   995         WriteL( aHeaderToWrite );
       
   996         DeleteServeFileL();
       
   997         }
       
   998     else // GET response and also sending POST message
       
   999         {
       
  1000         if ( iFileServe )
       
  1001             {
       
  1002             delete iFileServe;
       
  1003             iFileServe = NULL;
       
  1004             }
       
  1005 
       
  1006         iFileServe = CUpnpHttpFileAccess::NewL( this, aHeaderToWrite,
       
  1007             aPathWithNewMethod, aFileSize );
       
  1008 
       
  1009         if ( aStartPos != KErrNotFound )
       
  1010             iFileServe->SetPosOfFile( aStartPos );
       
  1011 
       
  1012         if ( aEndPos != KErrNotFound )
       
  1013             iFileServe->SetEndPosOfFile( aEndPos );
       
  1014 
       
  1015         if ( !FileTransferWriter() )
       
  1016             {
       
  1017             TInt requestedBytes = aRangeStatus == EHttpPartialContent
       
  1018                 ? aEndPos - aStartPos + 1 : aFileSize;
       
  1019             if ( requestedBytes <= HttpServer()->FileWriteBufferSize() )
       
  1020                 {
       
  1021                 FileTransferWriterConstructL( requestedBytes
       
  1022                         + aHeaderToWrite.Length() );
       
  1023                 }
       
  1024             else
       
  1025                 {
       
  1026                 FileTransferWriterConstructL(
       
  1027                     HttpServer()->FileWriteBufferSize() );
       
  1028                 }
       
  1029             }
       
  1030         FileTransferWriter()->Reset();
       
  1031 
       
  1032         if ( iOutFilename->Length() > 0 && iDestinationPath->Length() > 0 )
       
  1033             {
       
  1034             FileTransferWriter()->SetPostNotify();
       
  1035             }
       
  1036         FileTransferWriter()->StartL();
       
  1037         }
       
  1038     }
       
  1039 
       
  1040 // -----------------------------------------------------------------------------
       
  1041 // CUpnpHttpSession::FileServeExists
       
  1042 //
       
  1043 // -----------------------------------------------------------------------------
       
  1044 //
       
  1045 TBool CUpnpHttpSession::FileServeExists()
       
  1046     {
       
  1047     return iFileServe ? ETrue : EFalse;
       
  1048     }
       
  1049 
       
  1050 // -----------------------------------------------------------------------------
       
  1051 // CUpnpHttpSession::DeleteServeFileL
       
  1052 //
       
  1053 // -----------------------------------------------------------------------------
       
  1054 //
       
  1055 void CUpnpHttpSession::DeleteServeFileL()
       
  1056     {
       
  1057     LOGS1( "%i, CUpnpHttpSession::DeleteServeFileL()", iId );
       
  1058 
       
  1059     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1060         iAddr, EHttp200Ok );
       
  1061     CleanupStack::PushL( msg );
       
  1062     msg->SetType( EExportComplete );
       
  1063 
       
  1064     msg->SetSessionId( Id() );
       
  1065 
       
  1066     CleanupStack::Pop( msg );
       
  1067     iServer->ToReceiveStackD( msg );
       
  1068 
       
  1069     delete iFileServe;
       
  1070     iFileServe = NULL;
       
  1071 
       
  1072     if ( iPendingRequests->Count() > 0 )
       
  1073         {
       
  1074         CUpnpHttpMessage* request = (*iPendingRequests)[0];
       
  1075         iPendingRequests->Remove( 0 );
       
  1076         CleanupStack::PushL( request );
       
  1077         User::LeaveIfError( PrepareToServeFileL( request ) );
       
  1078         CleanupStack::PopAndDestroy( request );
       
  1079         }
       
  1080     }
       
  1081 
       
  1082 // -----------------------------------------------------------------------------
       
  1083 // CUpnpHttpSession::NotifyErrorL
       
  1084 //
       
  1085 // -----------------------------------------------------------------------------
       
  1086 //
       
  1087 void CUpnpHttpSession::NotifyErrorL( const TInt aError, TInt aInternalError )
       
  1088     {
       
  1089     LOGS2( "%i, CUpnpHttpSession::NotifyErrorL error = %i", iId,
       
  1090             aError );
       
  1091 
       
  1092     CUpnpHttpMessage* msg = NULL;
       
  1093     msg = RUpnpHttpMessageFactory::HttpResponseErrorL( RemoteHost(), aError );
       
  1094     msg->SetInternalError( aInternalError );
       
  1095     NotifyUpperLayerLD( msg );
       
  1096     }
       
  1097 
       
  1098 // -----------------------------------------------------------------------------
       
  1099 // CUpnpHttpSession::NotifyDisconnectL
       
  1100 //
       
  1101 // -----------------------------------------------------------------------------
       
  1102 //
       
  1103 void CUpnpHttpSession::NotifyDisconnectL( TInetAddr aAddr )
       
  1104     {
       
  1105     LOGS1( "%i, CUpnpHttpSession::NotifyDisconnectL", iId );
       
  1106 
       
  1107     if ( iSenderPath->Length() > 0 && iDestinationPath->Length() > 0 )
       
  1108         {
       
  1109         CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1110             aAddr, EHttpRequestTimeout );
       
  1111         CleanupStack::PushL( msg );
       
  1112         msg->SetInFilenameL( *iInFilename );
       
  1113         msg->SetInternalError( iSessionError );
       
  1114 
       
  1115         CleanupStack::Pop( msg );
       
  1116         NotifyUpperLayerLD( msg );
       
  1117 
       
  1118         if ( iReceivedMessage && iFileServe )
       
  1119             {
       
  1120             iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
       
  1121             }
       
  1122         }
       
  1123     else if ( iReceivedMessage && iReceivedMessage->Method() == KHttpPost )
       
  1124         {
       
  1125         if ( !iErrorNotified )
       
  1126             {
       
  1127             // incoming post failed
       
  1128             CUpnpHttpMessage* msg =
       
  1129                     RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
       
  1130                         EHttpRequestTimeout );
       
  1131             CleanupStack::PushL( msg );
       
  1132             msg->SetType( ETransferError );
       
  1133             msg->SetSessionId( Id() );
       
  1134             // get destination path
       
  1135             msg->SetDestinationPathL( iReceivedMessage->Target() );
       
  1136 
       
  1137             CleanupStack::Pop( msg );
       
  1138             iServer->ToReceiveStackD( msg );
       
  1139             iErrorNotified = ETrue;
       
  1140             }
       
  1141         }
       
  1142     }
       
  1143 
       
  1144 // -----------------------------------------------------------------------------
       
  1145 // CUpnpHttpSession::NotifyTimeoutL
       
  1146 //
       
  1147 // -----------------------------------------------------------------------------
       
  1148 //
       
  1149 void CUpnpHttpSession::NotifyTimeoutL()
       
  1150     {
       
  1151     if ( iReceivedMessage )
       
  1152         {
       
  1153         if ( iReceivedMessage->Method() == KHttpPost )
       
  1154             {
       
  1155             // incoming post failed
       
  1156             CUpnpHttpMessage* msg =
       
  1157                     RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
       
  1158                         EHttpRequestTimeout );
       
  1159             CleanupStack::PushL( msg );
       
  1160             msg->SetType( ETransferError );
       
  1161             msg->SetSessionId( Id() );
       
  1162 
       
  1163             // get destination path
       
  1164             msg->SetDestinationPathL( iReceivedMessage->Target() );
       
  1165 
       
  1166             CleanupStack::Pop( msg );
       
  1167             iServer->ToReceiveStackD( msg );
       
  1168             iErrorNotified = ETrue;
       
  1169             if ( iFileServe )
       
  1170                 iFileServe->DeleteFile();
       
  1171             }
       
  1172         else if ( iReceivedMessage->Method().Find( KHttp8 ) != KErrNotFound
       
  1173                 && iReceivedMessage->Target() == KHttpOkCode8 )
       
  1174             { // incoming response failed
       
  1175             CUpnpHttpMessage* msg =
       
  1176                     RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
       
  1177                         EHttpRequestTimeout );
       
  1178             CleanupStack::PushL( msg );
       
  1179             msg->SetType( ETransferError );
       
  1180 
       
  1181             // get destination path
       
  1182             msg->SetDestinationPathL( KNullDesC8 );
       
  1183             msg->SetSessionId( Id() );
       
  1184 
       
  1185             CleanupStack::Pop( msg );
       
  1186             iServer->ToReceiveStackD( msg );
       
  1187             iErrorNotified = ETrue;
       
  1188             }
       
  1189         else
       
  1190             { // incoming response failed
       
  1191             CUpnpHttpMessage* msg =
       
  1192                     RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
       
  1193                         EHttpRequestTimeout );
       
  1194             CleanupStack::PushL( msg );
       
  1195             msg->SetType( ETransferError );
       
  1196 
       
  1197             // get destination path
       
  1198             msg->SetDestinationPathL( iReceivedMessage->Target() );
       
  1199             msg->SetSessionId( Id() );
       
  1200             if ( iInFilename )
       
  1201                 {
       
  1202                 msg->SetInFilenameL( *iInFilename );
       
  1203 
       
  1204                 }
       
  1205             CleanupStack::Pop( msg );
       
  1206             iServer->ToReceiveStackD( msg );
       
  1207             iErrorNotified = ETrue;
       
  1208             }
       
  1209 
       
  1210         }
       
  1211     else
       
  1212         {
       
  1213         CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1214             iAddr, EHttpRequestTimeout );
       
  1215         CleanupStack::PushL( msg );
       
  1216         msg->SetType( ETransferError );
       
  1217 
       
  1218         // get destination path
       
  1219         msg->SetDestinationPathL( KNullDesC8 );
       
  1220         msg->SetSessionId( Id() );
       
  1221 
       
  1222         CleanupStack::Pop( msg );
       
  1223         iServer->ToReceiveStackD( msg );
       
  1224         iErrorNotified = ETrue;
       
  1225         }
       
  1226     }
       
  1227 
       
  1228 // -----------------------------------------------------------------------------
       
  1229 // CUpnpHttpSession::SocketServerBusyL
       
  1230 //
       
  1231 // -----------------------------------------------------------------------------
       
  1232 //
       
  1233 void CUpnpHttpSession::SocketServerBusyL( const TInetAddr& aAddr )
       
  1234     {
       
  1235     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1236         aAddr, EHttpExpectationFailed );
       
  1237     CleanupStack::PushL( msg );
       
  1238     msg->SetInFilenameL( *iInFilename );
       
  1239 
       
  1240     CleanupStack::Pop( msg );
       
  1241     NotifyUpperLayerLD( msg );
       
  1242 
       
  1243     if ( iReceivedMessage && iFileServe )
       
  1244         {
       
  1245         iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
       
  1246         }
       
  1247     }
       
  1248 
       
  1249 // -----------------------------------------------------------------------------
       
  1250 // CUpnpHttpSession::NotifyUpperLayerL
       
  1251 //
       
  1252 // -----------------------------------------------------------------------------
       
  1253 //
       
  1254 void CUpnpHttpSession::NotifyUpperLayerLD( CUpnpHttpMessage* aMessage )
       
  1255     {
       
  1256     LOGS2( "%i, CUpnpHttpSession::NotifyUpperLayerL %i", iId,
       
  1257             aMessage->Error( ) );
       
  1258     CleanupStack::PushL( aMessage );
       
  1259 
       
  1260     aMessage->SetSessionId( iId );
       
  1261 
       
  1262     if ( iPendingRequest )
       
  1263         {
       
  1264         aMessage->SetPendingRequest( iPendingRequest );
       
  1265         }
       
  1266     aMessage->SetSenderPathL( *iSenderPath );
       
  1267 
       
  1268     if ( aMessage->Method().FindC( KHttp11WithoutSpace ) == 0
       
  1269             || aMessage->Method().FindC( KHttp10 ) == 0 )
       
  1270         {
       
  1271         aMessage->SetDestinationPathL( *iDestinationPath );
       
  1272         }
       
  1273     else
       
  1274         {
       
  1275         TPtrC8 path = aMessage->SenderPathFromHeader();
       
  1276         aMessage->SetDestinationPathL( path );
       
  1277         }
       
  1278 
       
  1279     aMessage->SetType( iRequestType );
       
  1280     aMessage->SetRetryCounter( iRetryCounter );
       
  1281 
       
  1282     iDisconnectNotification = EFalse;
       
  1283     aMessage->SetOutFilenameL( *iOutFilename );
       
  1284     CleanupStack::Pop( aMessage );
       
  1285     iServer->ToReceiveStackD( aMessage );
       
  1286     }
       
  1287 
       
  1288 // -----------------------------------------------------------------------------
       
  1289 // CUpnpHttpSession::IsValidMessage
       
  1290 //
       
  1291 // -----------------------------------------------------------------------------
       
  1292 //
       
  1293 CUpnpHttpSession::THttpInvalidMessage CUpnpHttpSession::IsValidMessage(
       
  1294     CUpnpHttpMessage* aMsg )
       
  1295     {
       
  1296     // Checking method. METHOD NAMES ARE CASE SENSITIVE,
       
  1297     // so checking that method is OK.
       
  1298     // http://www.w3.org/Protocols/HTTP/Methods.html
       
  1299     if ( aMsg->Method().Find( KHttpGet() ) != 0 && aMsg->Method().Find(
       
  1300         KHttpPost() ) != 0 && aMsg->Method().Find( KHttpHead() ) != 0
       
  1301             && aMsg->Method().Find( KHttpOptions() ) != 0
       
  1302             && aMsg->Method().Find( KHttpPut() ) != 0 && aMsg->Method().Find(
       
  1303         KHttpDelete() ) != 0 && aMsg->Method().Find( KHttpTrace() ) != 0
       
  1304             && aMsg->Method().Find( KHttpConnect() ) != 0
       
  1305             && aMsg->Method().Find( KHttp11WithoutSpace() ) != 0
       
  1306             && aMsg->Method().Find( KHttp10() ) != 0 && aMsg->Method().Find(
       
  1307         UpnpGENA::KGenaSubscribe() ) != 0 && aMsg->Method().Find(
       
  1308         UpnpGENA::KGenaUnSubscribe() ) != 0 && aMsg->Method().Find(
       
  1309         UpnpGENA::KGenaNotify() ) != 0 )
       
  1310         {
       
  1311         return EUnknownMethod;
       
  1312         }
       
  1313     return EMessageOk;
       
  1314     }
       
  1315 
       
  1316 // -----------------------------------------------------------------------------
       
  1317 // CUpnpHttpSession::FileAccess
       
  1318 //
       
  1319 // -----------------------------------------------------------------------------
       
  1320 //
       
  1321 CUpnpHttpFileAccess* CUpnpHttpSession::FileAccess()
       
  1322     {
       
  1323     return iFileServe;
       
  1324     }
       
  1325 
       
  1326 // -----------------------------------------------------------------------------
       
  1327 // CUpnpHttpSession::OverwriteExisting
       
  1328 //
       
  1329 // -----------------------------------------------------------------------------
       
  1330 //
       
  1331 TBool CUpnpHttpSession::OverwriteExisting()
       
  1332     {
       
  1333     return iOverwriteExisting;
       
  1334     }
       
  1335 
       
  1336 // -----------------------------------------------------------------------------
       
  1337 // CUpnpHttpSession::Offset
       
  1338 //
       
  1339 // -----------------------------------------------------------------------------
       
  1340 //
       
  1341 TInt CUpnpHttpSession::Offset()
       
  1342     {
       
  1343     return iOffset;
       
  1344     }
       
  1345 
       
  1346 // -----------------------------------------------------------------------------
       
  1347 // CUpnpHttpSession::Length
       
  1348 //
       
  1349 // -----------------------------------------------------------------------------
       
  1350 //
       
  1351 TInt CUpnpHttpSession::Length()
       
  1352     {
       
  1353     return iLength;
       
  1354     }
       
  1355 
       
  1356 // -----------------------------------------------------------------------------
       
  1357 // CUpnpHttpSession::SaveAtOffset
       
  1358 //
       
  1359 // -----------------------------------------------------------------------------
       
  1360 //
       
  1361 TBool CUpnpHttpSession::SaveAtOffset()
       
  1362     {
       
  1363     return iSaveAtOffset;
       
  1364     }
       
  1365 
       
  1366 // -----------------------------------------------------------------------------
       
  1367 // CUpnpHttpSession::ServerPort
       
  1368 //
       
  1369 // -----------------------------------------------------------------------------
       
  1370 //
       
  1371 TInt CUpnpHttpSession::ServerPort()
       
  1372     {
       
  1373     return iServer->ServerPort();
       
  1374     }
       
  1375 
       
  1376 // -----------------------------------------------------------------------------
       
  1377 // CUpnpHttpSession::CheckConnectionClose
       
  1378 //
       
  1379 // -----------------------------------------------------------------------------
       
  1380 //
       
  1381 void CUpnpHttpSession::CheckConnectionCloseL()
       
  1382     {
       
  1383     LOGS1( "%i, CUpnpHttpSession::CheckConnectionCloseL", iId );
       
  1384 
       
  1385     if ( iReceivedMessage )
       
  1386         {
       
  1387         if ( iReceivedMessage->IsHeaderReady()
       
  1388                 && iReceivedMessage->UsesConnectionClose() )
       
  1389             {
       
  1390             TPtrC8 buffer = iReceivedMessage->Content();
       
  1391 
       
  1392             CUpnpHttpMessage* msg = NULL;
       
  1393             TInt err;
       
  1394                 TRAP( err, msg = CUpnpHttpMessage::NewL( buffer, RemoteHost( ),
       
  1395                                 iId ) );
       
  1396             CleanupStack::PushL( msg );
       
  1397             // If parsing error occurs, or 'stop transfer' occurs during export from other MS to this MS
       
  1398             // and the resource [file] isn't completely downloaded -> don't notify upper layers
       
  1399             if ( err < KErrNone || (err == KErrNone
       
  1400                     && (iReceivedMessage->Method().Find( KHttpPost ) == 0)
       
  1401                     && !iReceivedMessage->IsReadyL()) )
       
  1402                 {
       
  1403                 LOGS1H(
       
  1404                         iHandle,
       
  1405                         "%i, CUpnpHttpSession::CheckConnectionCloseL - parsing error",
       
  1406                         iId );
       
  1407 
       
  1408                 iReceivedMessage->RemoveL( buffer.Length() );
       
  1409                 StartDisconnect();
       
  1410                 CleanupStack::PopAndDestroy( msg );
       
  1411                 return;
       
  1412                 }
       
  1413 
       
  1414             msg->SetInFilenameL( *iInFilename );
       
  1415             if ( !iReceivedMessage->IsToFile()
       
  1416                     || (iReceivedMessage->IsToFile() && iFileServe
       
  1417                             && iFileServe->FileExist()) )
       
  1418                 {
       
  1419                 CleanupStack::Pop( msg );
       
  1420                 NotifyUpperLayerLD( msg );
       
  1421                 }
       
  1422             else
       
  1423                 {
       
  1424                 CleanupStack::PopAndDestroy( msg );
       
  1425                 }
       
  1426             iPendingRequest = NULL;
       
  1427             }
       
  1428         }
       
  1429     }
       
  1430 
       
  1431 // -----------------------------------------------------------------------------
       
  1432 // CUpnpHttpSession::NotifyUpperLayersOnPostL
       
  1433 //
       
  1434 // -----------------------------------------------------------------------------
       
  1435 //
       
  1436 void CUpnpHttpSession::NotifyUpperLayersOnPostL()
       
  1437     {
       
  1438     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseOkL(
       
  1439         RemoteHost() );
       
  1440 
       
  1441     CleanupStack::PushL( msg );
       
  1442 
       
  1443     CUpnpHttpHeaderList* List = NULL;
       
  1444     List = msg->HeaderList();
       
  1445 
       
  1446     CUpnpHttpHeader* hdr = List->First();
       
  1447 
       
  1448 	if(hdr != NULL)
       
  1449 	{
       
  1450 		HBufC8* newHeader = NULL;
       
  1451 		newHeader = HBufC8::NewLC( KTransferPending801().Length() );
       
  1452 		newHeader->Des().Zero();
       
  1453 		newHeader->Des().Append( KTransferPending801() );
       
  1454 
       
  1455 		hdr->SetNameL( *newHeader );
       
  1456 
       
  1457 		CleanupStack::PopAndDestroy( newHeader );
       
  1458 	}
       
  1459     msg->SetOutFilenameL( *iOutFilename );
       
  1460     CleanupStack::Pop( msg );
       
  1461     NotifyUpperLayerLD( msg );
       
  1462     }
       
  1463 
       
  1464 // -----------------------------------------------------------------------------
       
  1465 // CUpnpHttpSession::PostingFileCompleteL
       
  1466 //
       
  1467 // -----------------------------------------------------------------------------
       
  1468 //
       
  1469 void CUpnpHttpSession::PostingFileCompleteL()
       
  1470     {
       
  1471     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseOkL(
       
  1472         RemoteHost() );
       
  1473     CleanupStack::PushL( msg );
       
  1474     msg->SetOutFilenameL( *iOutFilename );
       
  1475 
       
  1476     CleanupStack::Pop( msg );
       
  1477     NotifyUpperLayerLD( msg );
       
  1478     }
       
  1479 
       
  1480 
       
  1481 // -----------------------------------------------------------------------------
       
  1482 //  CUpnpHttpSession::IsMsgReady
       
  1483 //
       
  1484 // -----------------------------------------------------------------------------
       
  1485 //
       
  1486 TBool CUpnpHttpSession::IsMsgReady()
       
  1487     {
       
  1488     TBool ret = EFalse;
       
  1489 
       
  1490     if ( iReceivedMessage )
       
  1491         {
       
  1492         TRAPD( err, ret = iReceivedMessage->IsReadyL( ) );
       
  1493 
       
  1494         if ( err != KErrNone )
       
  1495             return EFalse;
       
  1496 
       
  1497         return ret;
       
  1498         }
       
  1499     else
       
  1500         return EFalse;
       
  1501     }
       
  1502 
       
  1503 
       
  1504 // -----------------------------------------------------------------------------
       
  1505 //  CUpnpHttpSession::HttpServer()
       
  1506 // Returns pointer to the CUpnpHttpServer object
       
  1507 // -----------------------------------------------------------------------------
       
  1508 //
       
  1509 CUpnpHttpServer* CUpnpHttpSession::HttpServer()
       
  1510     {
       
  1511     return iServer;
       
  1512     }
       
  1513 
       
  1514 
       
  1515 // -----------------------------------------------------------------------------
       
  1516 //  CUpnpHttpSession::FileTransferReaderDoneL()
       
  1517 // Callback from file transfer reader
       
  1518 // -----------------------------------------------------------------------------
       
  1519 //
       
  1520 void CUpnpHttpSession::FileTransferReaderDoneL()
       
  1521     {
       
  1522     LOGS1( "%i, CUpnpHttpSession::FileTransferReaderDoneL", iId );
       
  1523     //notify import completed to upper layers
       
  1524     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1525         iAddr, EHttp200Ok );
       
  1526     CleanupStack::PushL( msg );
       
  1527     msg->SetType( EImportComplete );
       
  1528     msg->SetSessionId( Id() );
       
  1529     //setting it only for a POST request
       
  1530     msg->SetDestinationPathL( KNullDesC8 );
       
  1531     CleanupStack::Pop( msg );
       
  1532     iServer->ToReceiveStackD( msg );
       
  1533 
       
  1534     TPtrC8 headers = iReceivedMessage->Headers();
       
  1535     //original message received from the remote MS
       
  1536     CUpnpHttpMessage* original = CUpnpHttpMessage::NewL( (TDesC8&) headers,
       
  1537         RemoteHost(), iId );
       
  1538     CleanupStack::PushL( original );
       
  1539     original->SetInFilenameL( *iInFilename );
       
  1540     delete iFileServe;
       
  1541     iFileServe = NULL;
       
  1542     //notify POST is finished
       
  1543     //prepare reply 200 Ok for the remote MS
       
  1544     CUpnpHttpMessage* reply = RUpnpHttpMessageFactory::HttpResponseOkL(
       
  1545         original );
       
  1546     CleanupStack::PushL( reply );
       
  1547     reply->AddPairL( UpnpHTTP::KHdrServer(), iServer->ServerDescription() );
       
  1548     reply->AddPairL( UpnpHTTP::KConnection(), UpnpHTTP::KClose() );
       
  1549     HBufC8* sendBuf = reply->ToStringL();
       
  1550     CleanupStack::PopAndDestroy( reply );
       
  1551     CleanupStack::Pop( original );
       
  1552     //inform the upper layer
       
  1553     iServer->ToReceiveStackD( original );
       
  1554     CleanupStack::PushL( sendBuf );
       
  1555     //send reply to the client
       
  1556     WriteL( *sendBuf );
       
  1557     CleanupStack::PopAndDestroy( sendBuf );
       
  1558 
       
  1559     ResetSettingsL();
       
  1560 
       
  1561     }
       
  1562 
       
  1563 // -----------------------------------------------------------------------------
       
  1564 //  CUpnpHttpSession::FileTransferReaderDoneL()
       
  1565 // Callback from file transfer reader
       
  1566 // -----------------------------------------------------------------------------
       
  1567 //
       
  1568 void CUpnpHttpSession::FileTransferReaderErrorL( TInt aError )
       
  1569     {
       
  1570     LOGS1( "CUpnpHttpSession::FileTransferReaderErrorL %d", aError );
       
  1571     if ( iFileServe )
       
  1572         iFileServe->DeleteFile();
       
  1573     NotifyErrorL( aError );
       
  1574     if ( aError > 0 )
       
  1575         aError = -aError;
       
  1576     TInt httpError = MatchHttpError( aError );
       
  1577     if ( httpError != KErrNone )
       
  1578         {// If we act as a server side
       
  1579         ResponseErrorL( httpError );
       
  1580         ShutdownStop();
       
  1581         return;
       
  1582         }
       
  1583     ResetSettingsL();
       
  1584     }
       
  1585 
       
  1586 // -----------------------------------------------------------------------------
       
  1587 //  CUpnpHttpSession::ResetSettingsL()
       
  1588 // Callback from file transfer reader
       
  1589 // -----------------------------------------------------------------------------
       
  1590 //
       
  1591 void CUpnpHttpSession::ResetSettingsL()
       
  1592 
       
  1593     {
       
  1594     LOGS1( "%d, CUpnpHttpSession::ResetSettingsL", iId );
       
  1595     iContinuedMessageDownload = EFalse;
       
  1596     iHeadersCompleted = EFalse;
       
  1597 
       
  1598     delete iFileServe;
       
  1599     iFileServe = NULL;
       
  1600 
       
  1601     delete iReceivedMessage;
       
  1602     iReceivedMessage = NULL;
       
  1603 
       
  1604     delete iInFilename;
       
  1605     iInFilename = NULL;
       
  1606     iInFilename = HBufC8::NewMaxL( 0 );
       
  1607 
       
  1608     }
       
  1609 
       
  1610 // -----------------------------------------------------------------------------
       
  1611 // CUpnpHttpSession::FileTransferWriterDoneL
       
  1612 //
       
  1613 // -----------------------------------------------------------------------------
       
  1614 //
       
  1615 void CUpnpHttpSession::FileTransferWriterDoneL()
       
  1616     {
       
  1617 
       
  1618     LOGS1( "%i, CUpnpHttpSession::FileTransferWriterDoneL()", iId );
       
  1619 
       
  1620     CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
       
  1621         iAddr, EHttp200Ok );
       
  1622     CleanupStack::PushL( msg );
       
  1623     msg->SetType( EExportComplete );
       
  1624 
       
  1625     msg->SetSessionId( Id() );
       
  1626 
       
  1627     CleanupStack::Pop( msg );
       
  1628     iServer->ToReceiveStackD( msg );
       
  1629 
       
  1630     delete iFileServe;
       
  1631     iFileServe = NULL;
       
  1632 
       
  1633     iSessionNeedsErrorReply = EFalse;
       
  1634     }
       
  1635 
       
  1636 // -----------------------------------------------------------------------------
       
  1637 //  CUpnpHttpSession::FileTransferWriterHandleMoreL()
       
  1638 // Callback from file transfer writer
       
  1639 // -----------------------------------------------------------------------------
       
  1640 //
       
  1641 void CUpnpHttpSession::FileTransferWriterHandleMoreL()
       
  1642 
       
  1643     {
       
  1644     LOGS1( "%i, CUpnpHttpSession::FileTransferWriterHandleMoreL()",
       
  1645             iId );
       
  1646     if ( FileTransferWriter() )
       
  1647         FileTransferWriter()->Reset();
       
  1648 
       
  1649     if ( !IsPersistentConnection() )
       
  1650         {
       
  1651         StartClosingSession();
       
  1652         return;
       
  1653         }
       
  1654 
       
  1655     while ( iPendingRequests->Count() > 0 )
       
  1656         {
       
  1657         iSessionNeedsErrorReply = ETrue;
       
  1658 
       
  1659         CUpnpHttpMessage* request = (*iPendingRequests)[0];
       
  1660         iPendingRequests->Remove( 0 );
       
  1661         CleanupStack::PushL( request );
       
  1662         TInt error = PrepareToServeFileL( request );
       
  1663         CleanupStack::PopAndDestroy( request );
       
  1664 
       
  1665         if ( error )
       
  1666             {
       
  1667             NotifyErrorL( error );
       
  1668             if ( error > 0 )
       
  1669                 error = -error;
       
  1670             TInt httpError = MatchHttpError( error );
       
  1671             if ( httpError != KErrNone )
       
  1672                 {// If we act as a server side
       
  1673                 if ( iSessionNeedsErrorReply )
       
  1674                     {
       
  1675                     ResponseErrorL( httpError );
       
  1676                     }
       
  1677                 }
       
  1678 
       
  1679             if ( !IsPersistentConnection() )
       
  1680                 {
       
  1681                 StartClosingSession();
       
  1682                 }
       
  1683             }
       
  1684         else
       
  1685             {
       
  1686             break;
       
  1687             }
       
  1688         }
       
  1689     }
       
  1690 
       
  1691 // -----------------------------------------------------------------------------
       
  1692 //  CUpnpHttpSession::CheckSessionPersistence
       
  1693 // Checks if message contains CONNECTION:CLOSE
       
  1694 // -----------------------------------------------------------------------------
       
  1695 //
       
  1696 void CUpnpHttpSession::CheckSessionPersistence( CUpnpHttpMessage* aMsg )
       
  1697     {
       
  1698     if ( aMsg->GetHeaderValue( UpnpHTTP::KConnection() ).FindC(
       
  1699         UpnpHTTP::KClose() ) >= 0 || aMsg->RequestHTTPVersion() == KHttp10() )
       
  1700         {
       
  1701         iIsPersistent = EFalse;
       
  1702         }
       
  1703     else
       
  1704         {
       
  1705         iIsPersistent = ETrue;
       
  1706         }
       
  1707 
       
  1708     if ( !IsPersistentConnection() )
       
  1709         {
       
  1710         iSessionKeepAlive = EFalse;
       
  1711         }
       
  1712     }
       
  1713 
       
  1714 // -----------------------------------------------------------------------------
       
  1715 //  CUpnpHttpSession::DestroyIt()
       
  1716 //
       
  1717 // -----------------------------------------------------------------------------
       
  1718 //
       
  1719 void CUpnpHttpSession::DestroyIt( CUpnpTcpSession* aSession )
       
  1720     {
       
  1721     iServer->DeleteSession( aSession );
       
  1722     }
       
  1723 
       
  1724 // -----------------------------------------------------------------------------
       
  1725 //  CUpnpHttpSession::PrepareRangeHeaderL()
       
  1726 //
       
  1727 // -----------------------------------------------------------------------------
       
  1728 //
       
  1729 TInt CUpnpHttpSession::PrepareRangeHeaderL( CUpnpHttpMessage* aMsg,
       
  1730     TBool aServingOutFileName, TInt aFileSize,
       
  1731     CUpnpHttpServerTransaction &aTransaction, TInt& aRangeStatus, TInt& aStartPos, TInt& aEndPos )
       
  1732     {
       
  1733     // Generating headers
       
  1734     aStartPos = KErrNotFound;
       
  1735     aEndPos = KErrNotFound;
       
  1736 
       
  1737     // Check if there is a Range header in request and if it's correct
       
  1738     CUpnpRangeHeaderParser* rangeParser = CUpnpRangeHeaderParser::NewLC(
       
  1739         aTransaction, aStartPos, aEndPos );
       
  1740     aRangeStatus = rangeParser->ParseRangeL( aMsg, aFileSize );
       
  1741     CleanupStack::PopAndDestroy( rangeParser );
       
  1742 
       
  1743     if ( aRangeStatus != EHttpOk )
       
  1744         {
       
  1745         if ( aRangeStatus <= -EHttpBadRequest )
       
  1746             {
       
  1747             return aRangeStatus;
       
  1748             }
       
  1749         else if ( aRangeStatus == EHttpNoContent )
       
  1750             {
       
  1751             return KErrNone;
       
  1752             }
       
  1753         }
       
  1754     else
       
  1755         {
       
  1756         // Serve whole file
       
  1757         if ( !aServingOutFileName )
       
  1758             {
       
  1759             // If OutFilename() was set in msg
       
  1760             TBuf8<2 * KMaxIntegerLength> sizeBuffer;
       
  1761             sizeBuffer.Num( aFileSize );
       
  1762             aTransaction.AddResponseHeaderL( KNullDesC8(), UpnpHTTP::KHTTPOk() );
       
  1763             aTransaction.AddResponseHeaderL( UpnpHTTP::KHdrContentLength(), sizeBuffer );
       
  1764             }
       
  1765         else
       
  1766             {
       
  1767             // If file path was extracted from header
       
  1768             HBufC8* tempBuffer = aMsg->HeadersToStringL();
       
  1769             CleanupStack::PushL( tempBuffer );
       
  1770             aTransaction.AddResponseHeaderL( KNullDesC8(), *tempBuffer );
       
  1771             CleanupStack::PopAndDestroy( tempBuffer );
       
  1772             }            
       
  1773         }
       
  1774 
       
  1775     return  KErrNone;
       
  1776     }
       
  1777 
       
  1778 // -----------------------------------------------------------------------------
       
  1779 //  CUpnpHttpSession::PrepareRelativeUriL
       
  1780 //
       
  1781 // -----------------------------------------------------------------------------
       
  1782 //
       
  1783 TPtrC8 CUpnpHttpSession::PrepareRelativeUriL( const TDesC8& aUri )
       
  1784     {
       
  1785     TInetAddr resourceServerAddress;
       
  1786     iServer->ServerAddress( resourceServerAddress );
       
  1787     TInt portNo = iServer->ServerPort();
       
  1788     
       
  1789     TBuf<KMaxName> addrTmp;
       
  1790     resourceServerAddress.Output( addrTmp );
       
  1791     HBufC8* addr = UpnpString::FromUnicodeL( addrTmp );
       
  1792     CleanupStack::PushL( addr );
       
  1793     
       
  1794     TBuf8<KMaxName> port;
       
  1795     port.Num( portNo );
       
  1796     
       
  1797     TInt addrLength = UpnpHTTP::KHTTPUrl().Length() +  addr->Length( ) + UpnpString::KColon().Length( ) + port.Length( );
       
  1798     HBufC8* temp = HBufC8::NewLC( addrLength );
       
  1799     TPtr8 tempPtr( temp->Des() );
       
  1800     tempPtr.Append(  UpnpHTTP::KHTTPUrl );
       
  1801     tempPtr.Append( *addr );
       
  1802     tempPtr.Append( UpnpString::KColon );
       
  1803     tempPtr.Append( port );
       
  1804 
       
  1805     CleanupStack::Pop( temp );
       
  1806     CleanupStack::PopAndDestroy( addr );
       
  1807     
       
  1808     if ( aUri.Find( *temp ) == 0  )
       
  1809         {
       
  1810         delete temp;
       
  1811         return aUri.Mid( addrLength );
       
  1812         }
       
  1813     
       
  1814     delete temp;
       
  1815     return aUri; 
       
  1816     }
       
  1817 
       
  1818 // End Of File