upnp/upnpstack/dlnawebserver/src/upnphttpsession.cpp
changeset 0 f5a58ecadc66
child 9 5c72fd91570d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/dlnawebserver/src/upnphttpsession.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,1818 @@
+/** @file
+ * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies  this distribution, and is available 
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:  Declares HttpServer class.
+ *
+ */
+// INCLUDE FILES
+#include <in_sock.h>
+#include <e32std.h>
+#include <apgcli.h> // For RApaLsSession
+#include <apmstd.h>
+#include <escapeutils.h>
+#include <bautils.h>
+#include "upnphttpserver.h"
+#include "upnpstring.h"
+#include "upnpcons.h"
+#include "upnphttpsession.h"
+#include "upnphttpbuffer.h"
+#include "upnphttpfiletransferreader.h"
+#include "upnphttpfiletransferwriter.h"
+#include "upnphttpmessagefactory.h"
+#include "upnphttpheader.h"
+#include "upnperrors.h"
+#include "upnpcommonupnplits.h"
+#include "upnpfileutils.h"
+#define KLogFile _L("DLNAWebServer.txt")
+#include "upnpcustomlog.h"
+#include "upnphttpfileaccess.h"
+#include "httperr.h"
+#include "upnphttpservertransactioncreator.h"
+#include "upnprangeheaderparser.h"
+#include "upnphttpservertransaction.h"
+
+// CONSTANTS
+_LIT8( KTransferPending801, "HTTP/1.1 801 Transfer Pending");
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NewL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpSession* CUpnpHttpSession::NewL( RSocket aSocket,
+    CUpnpHttpServer* aServer, TInt aSessionId, TThreadPriority aPriority )
+    {
+    LOGS1(  "%i, CUpnpHttpSession::NewL - creating session for incoming connection",
+            aSessionId );
+
+    CUpnpHttpSession* self = new (ELeave) CUpnpHttpSession( aSocket, aServer,
+        aSessionId, aPriority );
+    CleanupStack::PushL( self );
+    self->TcpConstructL( aSocket, KRcvBufSizeDefault,
+        aServer->FileReadBufferSize() );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    LOGS1( "%i, CUpnpHttpSession::NewL - HTTP *** Created new session.",
+            self->Id( ) );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::CUpnpHttpSession
+// C++ default constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpSession::CUpnpHttpSession( RSocket aSocket,
+    CUpnpHttpServer* aServer, TInt aSessionId, TThreadPriority aPriority ) :
+    CUpnpTcpSession( aSocket, aPriority )
+    {
+    iId = aSessionId;
+    iServer = aServer;
+    iRequestedTransferNotifySent = EFalse;
+    // Assume that session should be kept alive unless the request
+    // with HTTP header "Connection: close" comes.
+    iSessionKeepAlive = ETrue;
+    iSessionIsDeletedAfterResponse = EFalse;
+    iUsesConnectionClose = EFalse;
+    iSaveToFile = EFalse;
+    iOverwriteExisting = EFalse;
+    iOffset = 0;
+    iLength = 0;
+    iSaveAtOffset = EFalse;
+    iMaximumSizeChecked = EFalse;
+    iHeadersCompleted = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::ConstructL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::ConstructL()
+    {
+    LOGS1( "%i, CUpnpHttpSession::ConstructL", iId );
+    iFileServe = NULL;
+
+    iDestinationPath = HBufC8::NewL( 0 );
+    iSenderPath = HBufC8::NewL( 0 );
+
+    iInFilename = HBufC8::NewL( 0 );
+    iOutFilename = HBufC8::NewL( 0 );
+
+    iPendingRequests = new (ELeave) RPointerArray<CUpnpHttpMessage> ( 1 );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::~CUpnpHttpSession
+// C++ default destructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpSession::~CUpnpHttpSession()
+    {
+    LOGS1( "%i, CUpnpHttpSession::~CUpnpHttpSession()", iId );
+
+    delete iFileServe;
+    delete iInFilename;
+    delete iOutFilename;
+    delete iDestinationPath;
+    delete iSenderPath;
+
+    if ( iPendingRequests )
+        {
+        iPendingRequests->ResetAndDestroy();
+        iPendingRequests->Close();
+        delete iPendingRequests;
+        }
+
+    // no deleting of iPendingRequest, it's not owned
+    iPendingRequest = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::SendL
+// Send HTTP message.
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::SendL( CUpnpHttpMessage* aMessage )
+    {
+    LOGS1( "%i, CUpnpHttpSession::SendL(CUpnpHttpMessage*)", iId );
+
+    if ( !IsConnected() )
+        {
+        return;
+        }
+
+    iSessionNeedsErrorReply = EFalse;
+
+    // Set senders and destination path
+    delete iSenderPath;
+    iSenderPath = NULL;
+    delete iDestinationPath;
+    iDestinationPath = NULL;
+
+    if ( aMessage->Method().Find( KHttp11WithoutSpace ) == 0 )
+        {
+        iSenderPath = HBufC8::NewL( 0 );
+        aMessage->AddPairL( UpnpHTTP::KHdrServer(),
+            iServer->ServerDescription() );
+        }
+    else
+        {
+        iSenderPath = aMessage->SenderPathFromHeader().AllocL();
+        }
+
+    iDestinationPath = aMessage->SenderPath().AllocL();
+
+    // Set other properties
+    iRequestType = aMessage->Type();
+    iRetryCounter = aMessage->RetryCounter();
+
+    if ( aMessage->PendingRequest() )
+        {
+        iPendingRequest = aMessage->PendingRequest();
+        }
+
+    //we assume that converting to UTF8 is already done by upper layers
+    HBufC8* buf = aMessage->ToStringL();
+    CleanupStack::PushL( buf );
+    WriteL( *buf );
+    CleanupStack::PopAndDestroy( buf );
+    if ( !iIsPersistent )
+        {
+        iSessionKeepAlive = EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::DeleteThisSessionL
+// Delete the session.
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::DeleteThisSessionL( CUpnpTcpSession* /*aSession*/)
+    {
+    LOGS1( "%i, CUpnpHttpSession::DeleteThisSessionL", iId );
+
+    if ( iReceivedMessage )
+        {
+        if ( iReceivedMessage->BytesInBuffer() > 0
+                && iReceivedMessage->IsReadyL() )
+            {
+            TPtrC8 content = iReceivedMessage->Content();
+            CUpnpHttpMessage* msg = CUpnpHttpMessage::NewL( content,
+                RemoteHost(), iId );
+            CleanupStack::PushL( msg );
+
+            msg->SetType( iRequestType );
+
+            msg->SetRetryCounter( iRetryCounter );
+
+            THttpInvalidMessage aVal;
+            aVal = IsValidMessage( msg );
+
+            switch ( aVal )
+                {
+
+                case EMessageOk:
+                    //HandleQuery will take ownership of msg object
+                    CleanupStack::Pop( msg );
+                    // Pass the message forward
+                    HandleQueryL( msg );
+                    break;
+
+                default:
+                    CleanupStack::PopAndDestroy( msg );
+                    break;
+                }
+            }
+        }
+
+    ShutdownStop();
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::DeleteFileIfExists
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::DeleteFileIfExists( TDesC16& aFilename )
+    {
+    iServer->FileSession().Delete( aFilename );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::MatchHttpError
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::MatchHttpError( TInt error )
+    {
+    TInt httpError = KErrNone;
+
+    if ( error == KErrDiskFull )
+        httpError = EHttpInsufficientStorage;
+    else if ( error == KErrOverflow ) //one of the reason can be if chunk value is > 2^32
+        httpError = EHttpInsufficientStorage;
+    else if ( error == KErrAbort ) //POST HTTP/1.1
+        httpError = EHttpBadRequest;
+    else if ( error == KErrGeneral || error == KErrHttpUnknownParseState ) // this error may occur e.g when ContentLengthL() leaves
+        httpError = EHttpBadRequest;
+    else if ( -error >= EHttpBadRequest ) // HTTP errors
+        httpError = -error;
+    else if ( error == KErrNoMemory )
+        httpError = EHttpEntityTooLarge; // OOM handling
+    else if ( error == KErrNotSupported )
+        httpError = EHttpNotFound; // no transaction
+    else
+        httpError = EHttpInternalServerError;
+
+    return httpError;
+
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::BufferReceivedL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::BufferReceivedL( TDesC8& aBuffer )
+    {
+
+    TInt index = 0;
+    TPtrC8 ptrIn( aBuffer );
+    iPendingPostRequests = ETrue;
+    //handling requests on the server-side
+    if ( ptrIn.Length() > KHttpPost().Length() )
+        {
+        TPtrC8 ptrInOffset( ptrIn.Mid( KHttpPost().Length() ) );
+
+        //this loop splits buffer if it includes more than one POST message
+        while ( (index = ptrInOffset.Find( KHttpPost() )) >= 0 )
+            {
+            TPtrC8 ptrL = ptrIn.Left( index + KHttpPost().Length() );
+            SinglePostBufferReceivedL( ptrL );
+            ptrIn.Set( ptrIn.Mid( index + KHttpPost().Length() ) );
+            ptrInOffset.Set( ptrIn.Mid( KHttpPost().Length() ) );
+            }
+        }
+    SinglePostBufferReceivedL( ptrIn );
+    iPendingPostRequests = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::SinglePostBufferReceivedL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::SinglePostBufferReceivedL( TDesC8& aBuffer )
+    {
+    TInt error = KErrNone;
+        TRAP( error, BufferReceivedProcessL( aBuffer ) )
+    LOGS2( "%i, CUpnpHttpSession::BufferReceivedL finished with error %i", iId, error );
+    if ( error != KErrNone )
+        {
+        //if session left - no continuation of file transfer
+        if ( iFTReader && iFTReader->Activated() )
+            {
+            iFTReader->SetActivated( EFalse );
+            if ( iFileServe )
+                iFileServe->DeleteFile();
+            }
+
+        TInt httpError = MatchHttpError( error );
+        if ( httpError != KErrNone )
+            {// If we act as a server side
+            ResponseErrorL( httpError );
+            if ( httpError == EHttpEntityTooLarge )
+                {
+                NotifyErrorL( httpError, error );
+                }
+            ShutdownStop();
+            return;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::BufferReceivedCheckingHeadersL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::BufferReceivedCheckingHeadersL( TDesC8& aBuffer )
+    {
+    // If iInFilename is defined, data should be saved in to a file,
+    // this is the case of incoming GET response and for following parts of POST request.
+    if ( iInFilename && iInFilename->Length() > 0 )
+        {
+        iSaveToFile = ETrue;
+
+        // If this flag was set it means that even previously message was not ment
+        // to be saved to file, now when the body is downloaded it will be saved to file.
+        if ( iContinuedMessageDownload && !iReceivedMessage->IsToFile() )
+            {
+            iReceivedMessage->SetToFile( ETrue );
+            }
+
+        // Check Maximum Size requirement, but do this only once
+        if ( !iMaximumSizeChecked )
+            {
+            //Make temp buffer to check content of incoming data,
+            //its possible that content-Length is too huge (>2^32)
+            CUpnpHttpBuffer* checkBuf = CUpnpHttpBuffer::NewL( this, EFalse );
+            CleanupStack::PushL( checkBuf );
+            //leaves in case of problems with string operation, no HTTP error
+            checkBuf->AppendHeadersL( aBuffer, iSaveToFile );
+
+            if ( checkBuf->IsHeaderReady() )
+                {
+                // Now headers were checked
+                iHeadersCompleted = ETrue;
+                TRAPD( error, checkBuf->ContentLengthL( ) );
+                if ( error )
+                    {
+                    iSaveToFile = EFalse;
+                    }
+                iMaximumSizeChecked = ETrue;
+
+                //mark chunked encoding
+                iIsChunked = checkBuf->IsChunked();
+                //mark if persistent connection
+                if ( IsPersistentConnection() )
+                    iIsPersistent = !checkBuf->UsesConnectionClose();
+                }
+            else
+                {
+                iSaveToFile = EFalse;
+                }
+
+            CleanupStack::PopAndDestroy( checkBuf );
+            }
+        }
+    // Checking that if file is a POST that needs to be saved to a file. Only check this
+    // for the first time (iFileServe does not exist only on receiving the first buffer of data)
+    else if ( !iFileServe )
+        {
+        // making temp buffer to check content of incoming data
+        CUpnpHttpBuffer* checkBuf = CUpnpHttpBuffer::NewL( this, EFalse );
+        CleanupStack::PushL( checkBuf );
+        //leaves in case of problems with string operation, no HTTP error
+        checkBuf->AppendHeadersL( aBuffer, iSaveToFile );
+
+        if ( checkBuf->IsHeaderReady() )
+            {
+            // Now headers were checked
+            iHeadersCompleted = ETrue;
+
+            TPtrC8 headers = checkBuf->Headers();
+            CUpnpHttpMessage* tempMsg = NULL;
+            TRAPD( err, tempMsg = CUpnpHttpMessage::NewL( (TDesC8&) headers,
+                            RemoteHost( ), iId ) );
+
+            //POST HTTP/1.1
+            if ( err == KErrAbort )
+                {
+                if ( checkBuf->Method().Find( KHttpPost ) == 0 )
+                    //leaves in case of HTTP error for a POST
+                    User::Leave( KErrAbort );
+                }
+            else if ( err < KErrNone )
+                {
+                User::Leave( err );
+                }
+            else if ( err == KErrNone )
+                {
+                CleanupStack::PushL( tempMsg );
+
+                // Check method and make decision about handling message.
+                // It's a POST message
+                if ( tempMsg->Method().Find( KHttpPost ) == 0 )
+                    {
+                    // 100-Continue check should be done for all types of POST reqests, even for GENAs and SOAPs
+
+                    // First thing to do in case of upload is to chceck if there
+                    // is sufficient disk space to save incoming file.
+                    TUint fileSize = 0;
+                    TBool hasCL;
+                    TLex8 cntLength( tempMsg->IsHeader(
+                        UpnpHTTP::KHdrContentLength, hasCL ) );
+                    if ( hasCL )
+                        {
+                        TInt errorLength = cntLength.Val( fileSize );
+                        if ( errorLength == KErrOverflow )
+                            {
+                            iSaveToFile = EFalse;
+                            //leaves in case of HTTP error
+                            User::Leave( -EHttpInsufficientStorage );
+                            }
+                        else if ( errorLength != KErrNone )
+                            {
+                            iSaveToFile = EFalse;
+                            //leaves in case of HTTP error
+                            User::Leave( errorLength );
+                            }
+                        }
+                    //First check URI, because there is no sense in sending 100 continue for invalid URI
+                    if (!(tempMsg->IsGena()) && !(tempMsg->IsSoap()))
+                        {
+                        //response is sent inside function
+
+                        delete iInFilename;
+                        iInFilename = NULL;
+                        
+                        if ( !iServer->TransactionCreator() )
+                            {
+                            User::Leave( KErrNotSupported );
+                            }
+                        if ( UpnpFileUtil::ParseUri( tempMsg->SenderPathFromHeader() ) 
+                             != KErrNone )
+                            {
+                            iInFilename = KNullDesC8().AllocL();
+                            iSaveToFile = EFalse;
+                            User::Leave( -EHttpBadRequest );
+                            }
+                        TPtrC8 relativeUri = PrepareRelativeUriL( tempMsg->SenderPathFromHeader() );
+                        CUpnpHttpServerTransaction* transactionOut;
+                        iServer->TransactionCreator()->NewTransactionL(
+                                tempMsg->Method(), relativeUri,
+                                tempMsg->Sender(), transactionOut );
+                        CleanupStack::PushL( transactionOut );
+
+                        transactionOut->SetRequest(tempMsg);
+                        transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnRequestStart );
+                        
+                        iSaveToFile = EFalse;
+                        User::LeaveIfError( transactionOut->Error() );
+                        RBuf fileName;
+                        fileName.CreateL( KMaxFileName );
+                        CleanupClosePushL( fileName );
+                        User::LeaveIfError( transactionOut->DataSink().FullName( fileName ) );
+                        iInFilename = UpnpString::FromUnicodeL( fileName );
+                        iSaveToFile = ETrue;
+                        CleanupStack::PopAndDestroy(&fileName);
+                        
+                        transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnComplete );
+                        CleanupStack::PopAndDestroy( transactionOut );
+                        }
+
+                    
+                    //Maximum size was checked already so don't do this again
+                    iMaximumSizeChecked = ETrue;
+
+                    // If client sends Expect: 100-continue header then it must be checked
+                    // if file can be saved and if so, server should responds with 100.
+                    if ( tempMsg->GetHeaderValue( UpnpHTTP::KHdrExpect ).FindC(
+                        UpnpHTTP::K100Continue ) == 0 )
+                        {
+
+                        // Check disk space and ContentLength limit (2^32) and if it's not sufficient send 507 response and
+                        // close connection - sugested behaviour from DLNA 1.5 spec.
+
+                        HBufC16* pathTmp = NULL;
+                        pathTmp = UpnpString::ToUnicodeL( iInFilename->Des() );
+                        CleanupStack::PushL( pathTmp );
+
+                        TBool noSpace = UpnpFileUtil::CheckDiskSpaceShortL(
+                            pathTmp->Des(), fileSize, iServer->FileSession() );
+                        CleanupStack::PopAndDestroy( pathTmp );
+
+                        if ( noSpace )
+                            {
+                            iSaveToFile = EFalse;
+                            //leaves in case of HTTP error
+                            User::Leave( -EHttpInsufficientStorage );
+                            }
+                        else
+                            {
+                            // Set the flag informing that current message's body will
+                            // should be downloaded in some time
+                            iContinuedMessageDownload = ETrue;
+
+                            // If there is enough space to save incoming file send response 100,
+                            // which means that client can continue with sending the body.
+                            CUpnpHttpMessage* reply =
+                                    RUpnpHttpMessageFactory::Http11ResponseL(
+                                        tempMsg, EHttpContinue );
+                            CleanupStack::PushL( reply );
+                            HBufC8* sendBuf = reply->ToStringL();
+                            CleanupStack::PushL( sendBuf );
+                            WriteL( *sendBuf );
+                            CleanupStack::PopAndDestroy( sendBuf );
+                            CleanupStack::PopAndDestroy( reply );
+                            }
+
+                        }
+                    }
+                if ( iSaveToFile )
+                    {
+                    CleanupStack::Pop( tempMsg );
+                    tempMsg->SetType( ETransferStart );
+                    iServer->ToReceiveStackD( tempMsg );
+                    }
+                else
+                    {
+                    CleanupStack::PopAndDestroy( tempMsg );
+                    }
+                }
+            }
+        //mark if chunked encoding
+        iIsChunked = checkBuf->IsChunked();
+        //mark if persistent connection
+        if ( IsPersistentConnection() )
+            iIsPersistent = !checkBuf->UsesConnectionClose();
+        CleanupStack::PopAndDestroy( checkBuf );
+        }
+    else
+        {
+        iSaveToFile = EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::BufferReceivedProcessL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::BufferReceivedProcessL( TDesC8& aBuffer )
+    {
+    TInt httpError;
+    LOGS1( "%i, CUpnpHttpSession::BufferReceivedProcessL", iId );
+
+    if ( !iHeadersCompleted && iReceivedMessage )
+        {
+        // If all headers aren't completed after receiving a few data chunks,
+        // enlarge the buffer and try again.
+        HBufC8* headers = HBufC8::NewLC( iReceivedMessage->Content().Length()
+                + aBuffer.Length() );
+
+        headers->Des().Zero();
+        headers->Des().Append( iReceivedMessage->Content() );
+        headers->Des().Append( aBuffer );
+        //returns HTTP error only in case of a POST
+        BufferReceivedCheckingHeadersL( *headers );
+        CleanupStack::PopAndDestroy( headers );
+        }
+    else if ( !iHeadersCompleted && !iReceivedMessage )
+        {
+        // The first data chunk, both variables are not set. returns HTTP error only in case of a POST
+        BufferReceivedCheckingHeadersL( aBuffer );
+        }
+
+    // If message content should be saved to file then create a file access object
+    // that takes care of this operation.
+    if ( iSaveToFile && !iFileServe )
+        {
+        HBufC16* name = NULL;
+        name = UpnpString::ToUnicodeL( *iInFilename );
+        CleanupStack::PushL( name );
+        iFileServe = CUpnpHttpFileAccess::NewL( this, *name );
+        CleanupStack::PopAndDestroy( name );
+
+        // If it's response for Range reqest then setup range saving parameters in iFileServe
+        if ( iSaveAtOffset )
+            {
+            iFileServe->SetPosOfFile( iOffset );
+            iFileServe->SetEndPosOfFile( iOffset + Length() - 1 );
+            }
+
+        delete iInFilename;
+        iInFilename = NULL;
+
+        iInFilename = UpnpString::FromUnicodeL( iFileServe->FileToServe() );
+        }
+    //initiate filetransfer component
+    if ( iSaveToFile && iFileServe )
+        {
+        //file transfer reader
+        iFileServe->SetEncodingMode( iIsChunked );
+        FileTransferReaderConstructL();
+        }
+
+    if ( !iReceivedMessage )
+        {
+        iReceivedMessage = CUpnpHttpBuffer::NewL( this, iSaveToFile );
+        }
+    //leaves in case of problems with string operation, no HTTP error
+    User::LeaveIfError( iReceivedMessage->AppendL( aBuffer, iSaveToFile ) );
+
+    // This 'if statement' is required for proper deleting partial file
+    // when 'stop transfer' was invoked during exporting the resource from other MS.
+    if ( iFileServe && iReceivedMessage )
+        iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
+
+    
+    if ( FileTransferReader() && FileTransferReader()->Activated() )
+        return;
+    // Finish receiving message and handle query contained in message.
+    // Processing goes on and on till the incoming buffer is empty -
+    // this is the way the pipelining is handled.
+    while ( iReceivedMessage->IsReadyL() )
+        {
+
+        TPtrC8 buffer = iReceivedMessage->Content();
+
+        CUpnpHttpMessage* msg = NULL;
+        TInt err( KErrNone );
+            TRAP( err, msg = CUpnpHttpMessage::NewL( buffer, RemoteHost( ), iId ) );
+        CleanupStack::PushL( msg );
+
+        if ( err < KErrNone )
+            {
+            LOGS1(
+                    "%i, CUpnpHttpSession::BufferReceivedProcessL - failed", iId );
+
+            // sending response to remote host: bad request
+            httpError = MatchHttpError( -EHttpBadRequest );
+            if ( httpError != KErrNone )
+                {// If we act as a server side
+                ResponseErrorL( httpError );
+                }
+            CleanupStack::PopAndDestroy( msg );
+            }
+        else
+            {
+            iSessionKeepAlive = ETrue;
+            if ( IsPersistentConnection() )
+                if ( !iFileServe && iPendingRequests->Count() == 0 )
+                    if ( msg->GetHeaderValue( UpnpHTTP::KConnection() ).FindC(
+                        UpnpHTTP::KClose() ) >= 0
+                            || msg->RequestHTTPVersion() == KHttp10() )
+                        {
+                        iIsPersistent = EFalse;
+                        }
+
+            if ( !IsPersistentConnection() && !msg->IsSoap()
+                    && !msg->IsGena() )
+                {
+                iSessionKeepAlive = EFalse;
+                }
+
+            msg->SetType( iRequestType );
+
+            msg->SetSessionId( iId );
+
+            msg->SetRetryCounter( iRetryCounter );
+
+            if ( (iSaveToFile) && (iInFilename) )
+                {
+                msg->SetInFilenameL( iInFilename->Des() );
+                }
+
+            THttpInvalidMessage aVal;
+            aVal = IsValidMessage( msg );
+
+            switch ( aVal )
+                {
+                case EMessageOk:
+                    //HandleQueryL will take ownership of msg object
+                    CleanupStack::Pop( msg );
+                    TRAP( err, HandleQueryL( msg ) );
+                    if ( err < KErrNone ) 
+                        {
+                        httpError = MatchHttpError( err );
+                        if ( httpError != KErrNone )
+                            {// If we act as a server side
+                            ResponseErrorL( httpError );
+                            }
+                        }
+
+                    break;
+
+                case EUnknownMethod:
+                    {
+                    LOGS1H(
+                            iHandle,
+                            "%i, CUpnpHttpSession::BufferReceivedL - Unknown method",
+                            iId );
+
+                    httpError = MatchHttpError( -EHttpMethodNotAllowed );
+                    if ( httpError != KErrNone )
+                        {// If we act as a server side
+                        ResponseErrorL( httpError );
+                        }
+                    CleanupStack::PopAndDestroy( msg );
+                    }
+                    break;
+
+                default:
+                    LOGS1(
+                            "%i, CUpnpHttpSession::BufferReceivedL - failed", iId );
+                    CleanupStack::PopAndDestroy( msg );
+                    break;
+                };
+
+            }
+
+        // No continued message download is expected because
+        // the message processing is finished
+        iContinuedMessageDownload = EFalse;
+        iReceivedMessage->RemoveL( buffer.Length() );
+
+        iHeadersCompleted = EFalse;
+
+        delete iInFilename;
+        iInFilename = NULL;
+        iInFilename = HBufC8::NewL( 0 );
+
+        if ( iSessionIsDeletedAfterResponse )
+            {
+            StartDisconnect();
+            }
+        }
+
+    if ( iReceivedMessage->BytesInBuffer() <= 0 )
+        {
+        delete iReceivedMessage;
+        iReceivedMessage = NULL;
+        if ( iSessionIsDeletedAfterResponse )
+            {
+            StartDisconnect();
+            }
+        else
+            {
+            StartTimeoutTimer( iSessionNeedsErrorReply );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::ResponseErrorL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::ResponseErrorL( TInt aStatus )
+    {
+    LOGS2( "%i, CUpnpHttpSession::ResponseErrorL - error code %i",
+            iId, aStatus );
+
+    CUpnpHttpMessage* reply = NULL;
+    reply = RUpnpHttpMessageFactory::HttpResponseErrorL( RemoteHost(),
+        aStatus );
+    CleanupStack::PushL( reply );
+
+    reply->AddPairL( UpnpHTTP::KHdrServer(), iServer->ServerDescription() );
+    reply->SetSessionId( Id() );
+    reply->SetDestinationPathL( *iDestinationPath );
+    reply->SetSenderPathL( *iSenderPath );
+
+    HBufC8* sendBuf = reply->ToStringL();
+    CleanupStack::PushL( sendBuf );
+    WriteL( *sendBuf );
+    CleanupStack::PopAndDestroy( sendBuf );
+    CleanupStack::PopAndDestroy( reply );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::HandleQueryL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::HandleQueryL( CUpnpHttpMessage* aMsg )
+    {
+    LOGS1( "%i, CUpnpHttpSession::HandleQueryL", iId );
+    CleanupStack::PushL( aMsg );
+    
+    // Handle GET and HEAD requests
+    if ( aMsg->Method().Find( KHttpGet ) == 0 || aMsg->Method().Find(
+        KHttpHead ) == 0 )
+        {
+        // method starts with GET or HEAD
+        if ( FileServeExists() || (FileTransferWriter()
+                && FileTransferWriter()->IsActive()) )
+            {
+            User::LeaveIfError( iPendingRequests->Append( aMsg ) );
+            CleanupStack::Pop( aMsg );
+            }
+        else
+            {
+            User::LeaveIfError( PrepareToServeFileL( aMsg ) );
+            CleanupStack::PopAndDestroy( aMsg );
+            aMsg = NULL;
+            }
+        }
+
+    // Handle GENA, SOAP, responses, other messages etc.
+    else
+        {
+        aMsg->SetInFilenameL( *iInFilename );
+        delete iInFilename;
+        iInFilename = NULL;
+        iInFilename = HBufC8::NewL( 0 );
+        if ( !aMsg->Is1xx() )
+            {
+            CleanupStack::Pop( aMsg );
+            NotifyUpperLayerLD( aMsg );
+            iPendingRequest = NULL;
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy( aMsg );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::PrepareToServeFileL
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::PrepareToServeFileL( CUpnpHttpMessage* aMsg )
+    {
+
+    LOGS1( "%i, CUpnpHttpSession::PrepareToServeFileL", iId );
+    if ( !iServer->TransactionCreator() )
+         {
+         User::Leave( KErrNotSupported ); 
+         }
+    
+    CheckSessionPersistence( aMsg );
+    TInt parseUrlError = UpnpFileUtil::ParseUri( aMsg->SenderPathFromHeader() );
+    if ( parseUrlError != KErrNone )
+        {
+        return -EHttpBadRequest;
+        }
+    
+    TPtrC8 relativeUri = PrepareRelativeUriL( aMsg->SenderPathFromHeader() );
+    
+    CUpnpHttpServerTransaction* transactionOut; 
+    iServer->TransactionCreator()->NewTransactionL( aMsg->Method() ,
+            relativeUri, aMsg->Sender(), transactionOut );    
+    CleanupStack::PushL( transactionOut );
+    
+    transactionOut->SetRequest( aMsg );    
+    transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnRequestStart );
+    TInt error = transactionOut->Error();
+    if( error != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( transactionOut ); 
+        return error;
+        }
+                 
+    // 2. Try to open requested file
+    RFile& file = transactionOut->DataSource();
+    
+    TInt fileSize = -1;    
+    if( file.Size( fileSize ) != KErrNone  )
+        {
+        fileSize = -1;
+        }
+
+    TBool servingOutFilename = ( aMsg->OutFilename().Length() > 0 );
+
+    TInt result( KErrNone );
+    // 3. If file was opened it means it exists and might be served
+    if ( fileSize >= 0 )
+        {
+        TInt rangeStatus;
+        TInt startPos;
+        TInt endPos;
+        TInt errorValue;
+        errorValue = PrepareRangeHeaderL( 
+            aMsg, servingOutFilename, fileSize, *transactionOut,
+            rangeStatus, startPos, endPos );
+        
+        if ( errorValue == KErrNone )
+            {
+            if ( EHttpNoContent == rangeStatus )
+                {
+                transactionOut->AddResponseHeaderL( UpnpHTTP::KHdrServer(),
+                                                    iServer->ServerDescription() );             
+             
+                WriteL( transactionOut->QueryResponseHeader() );
+                }
+            else
+                {
+                transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnResponseStart );
+                //last header fiished by double CRLF so we must add last CRLF
+
+                errorValue = transactionOut->Error();
+                if ( errorValue != KErrNone  ) 
+                    {
+                        CleanupStack::PopAndDestroy( transactionOut );
+                        return errorValue;
+                    }
+                if ( transactionOut->QueryResponseHeader().Length() > 0 )
+                    {
+                    transactionOut->AddResponseHeaderL( UpnpHTTP::KHdrServer(),
+                                                        iServer->ServerDescription() );             
+                    RBuf fileName;
+                    fileName.CreateL( KMaxFileName );
+                    CleanupClosePushL( fileName );
+                    User::LeaveIfError( file.FullName( fileName ) );
+                    WriteMsgAndHeaderL( aMsg, transactionOut->QueryResponseHeader(),
+                        fileName, fileSize, rangeStatus, startPos, endPos );
+                    CleanupStack::PopAndDestroy( &fileName );
+                    }
+                }
+            }
+        result = errorValue;
+        }
+    else // 4. File was not found, so just respose with HTTP 404 error.
+        {
+
+        if ( !iSaveToFile )
+            {
+            //error. No such file or folder found. Send error message.
+            result = -EHttpNotFound;
+            }
+        }
+    if ( KErrNone == result )
+        {
+        result = transactionOut->Error();
+        }    
+
+    
+    transactionOut->OnCallbackL( CUpnpHttpServerTransaction::EOnComplete );
+    CleanupStack::PopAndDestroy( transactionOut );
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::WriteMsgAndHeaderL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::WriteMsgAndHeaderL( CUpnpHttpMessage* aMsg,
+    const TDesC8& aHeaderToWrite, const TDesC& aPathWithNewMethod,
+    TInt aFileSize, TInt aRangeStatus, const TInt aStartPos,
+    const TInt aEndPos )
+    {
+    if ( aMsg->Method().Find( KHttpHead ) == 0 ) // HEAD - just header
+        {
+        WriteL( aHeaderToWrite );
+        DeleteServeFileL();
+        }
+    else // GET response and also sending POST message
+        {
+        if ( iFileServe )
+            {
+            delete iFileServe;
+            iFileServe = NULL;
+            }
+
+        iFileServe = CUpnpHttpFileAccess::NewL( this, aHeaderToWrite,
+            aPathWithNewMethod, aFileSize );
+
+        if ( aStartPos != KErrNotFound )
+            iFileServe->SetPosOfFile( aStartPos );
+
+        if ( aEndPos != KErrNotFound )
+            iFileServe->SetEndPosOfFile( aEndPos );
+
+        if ( !FileTransferWriter() )
+            {
+            TInt requestedBytes = aRangeStatus == EHttpPartialContent
+                ? aEndPos - aStartPos + 1 : aFileSize;
+            if ( requestedBytes <= HttpServer()->FileWriteBufferSize() )
+                {
+                FileTransferWriterConstructL( requestedBytes
+                        + aHeaderToWrite.Length() );
+                }
+            else
+                {
+                FileTransferWriterConstructL(
+                    HttpServer()->FileWriteBufferSize() );
+                }
+            }
+        FileTransferWriter()->Reset();
+
+        if ( iOutFilename->Length() > 0 && iDestinationPath->Length() > 0 )
+            {
+            FileTransferWriter()->SetPostNotify();
+            }
+        FileTransferWriter()->StartL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::FileServeExists
+//
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpSession::FileServeExists()
+    {
+    return iFileServe ? ETrue : EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::DeleteServeFileL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::DeleteServeFileL()
+    {
+    LOGS1( "%i, CUpnpHttpSession::DeleteServeFileL()", iId );
+
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+        iAddr, EHttp200Ok );
+    CleanupStack::PushL( msg );
+    msg->SetType( EExportComplete );
+
+    msg->SetSessionId( Id() );
+
+    CleanupStack::Pop( msg );
+    iServer->ToReceiveStackD( msg );
+
+    delete iFileServe;
+    iFileServe = NULL;
+
+    if ( iPendingRequests->Count() > 0 )
+        {
+        CUpnpHttpMessage* request = (*iPendingRequests)[0];
+        iPendingRequests->Remove( 0 );
+        CleanupStack::PushL( request );
+        User::LeaveIfError( PrepareToServeFileL( request ) );
+        CleanupStack::PopAndDestroy( request );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NotifyErrorL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::NotifyErrorL( const TInt aError, TInt aInternalError )
+    {
+    LOGS2( "%i, CUpnpHttpSession::NotifyErrorL error = %i", iId,
+            aError );
+
+    CUpnpHttpMessage* msg = NULL;
+    msg = RUpnpHttpMessageFactory::HttpResponseErrorL( RemoteHost(), aError );
+    msg->SetInternalError( aInternalError );
+    NotifyUpperLayerLD( msg );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NotifyDisconnectL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::NotifyDisconnectL( TInetAddr aAddr )
+    {
+    LOGS1( "%i, CUpnpHttpSession::NotifyDisconnectL", iId );
+
+    if ( iSenderPath->Length() > 0 && iDestinationPath->Length() > 0 )
+        {
+        CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+            aAddr, EHttpRequestTimeout );
+        CleanupStack::PushL( msg );
+        msg->SetInFilenameL( *iInFilename );
+        msg->SetInternalError( iSessionError );
+
+        CleanupStack::Pop( msg );
+        NotifyUpperLayerLD( msg );
+
+        if ( iReceivedMessage && iFileServe )
+            {
+            iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
+            }
+        }
+    else if ( iReceivedMessage && iReceivedMessage->Method() == KHttpPost )
+        {
+        if ( !iErrorNotified )
+            {
+            // incoming post failed
+            CUpnpHttpMessage* msg =
+                    RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
+                        EHttpRequestTimeout );
+            CleanupStack::PushL( msg );
+            msg->SetType( ETransferError );
+            msg->SetSessionId( Id() );
+            // get destination path
+            msg->SetDestinationPathL( iReceivedMessage->Target() );
+
+            CleanupStack::Pop( msg );
+            iServer->ToReceiveStackD( msg );
+            iErrorNotified = ETrue;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NotifyTimeoutL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::NotifyTimeoutL()
+    {
+    if ( iReceivedMessage )
+        {
+        if ( iReceivedMessage->Method() == KHttpPost )
+            {
+            // incoming post failed
+            CUpnpHttpMessage* msg =
+                    RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
+                        EHttpRequestTimeout );
+            CleanupStack::PushL( msg );
+            msg->SetType( ETransferError );
+            msg->SetSessionId( Id() );
+
+            // get destination path
+            msg->SetDestinationPathL( iReceivedMessage->Target() );
+
+            CleanupStack::Pop( msg );
+            iServer->ToReceiveStackD( msg );
+            iErrorNotified = ETrue;
+            if ( iFileServe )
+                iFileServe->DeleteFile();
+            }
+        else if ( iReceivedMessage->Method().Find( KHttp8 ) != KErrNotFound
+                && iReceivedMessage->Target() == KHttpOkCode8 )
+            { // incoming response failed
+            CUpnpHttpMessage* msg =
+                    RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
+                        EHttpRequestTimeout );
+            CleanupStack::PushL( msg );
+            msg->SetType( ETransferError );
+
+            // get destination path
+            msg->SetDestinationPathL( KNullDesC8 );
+            msg->SetSessionId( Id() );
+
+            CleanupStack::Pop( msg );
+            iServer->ToReceiveStackD( msg );
+            iErrorNotified = ETrue;
+            }
+        else
+            { // incoming response failed
+            CUpnpHttpMessage* msg =
+                    RUpnpHttpMessageFactory::HttpResponseErrorL( iAddr,
+                        EHttpRequestTimeout );
+            CleanupStack::PushL( msg );
+            msg->SetType( ETransferError );
+
+            // get destination path
+            msg->SetDestinationPathL( iReceivedMessage->Target() );
+            msg->SetSessionId( Id() );
+            if ( iInFilename )
+                {
+                msg->SetInFilenameL( *iInFilename );
+
+                }
+            CleanupStack::Pop( msg );
+            iServer->ToReceiveStackD( msg );
+            iErrorNotified = ETrue;
+            }
+
+        }
+    else
+        {
+        CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+            iAddr, EHttpRequestTimeout );
+        CleanupStack::PushL( msg );
+        msg->SetType( ETransferError );
+
+        // get destination path
+        msg->SetDestinationPathL( KNullDesC8 );
+        msg->SetSessionId( Id() );
+
+        CleanupStack::Pop( msg );
+        iServer->ToReceiveStackD( msg );
+        iErrorNotified = ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::SocketServerBusyL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::SocketServerBusyL( const TInetAddr& aAddr )
+    {
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+        aAddr, EHttpExpectationFailed );
+    CleanupStack::PushL( msg );
+    msg->SetInFilenameL( *iInFilename );
+
+    CleanupStack::Pop( msg );
+    NotifyUpperLayerLD( msg );
+
+    if ( iReceivedMessage && iFileServe )
+        {
+        iFileServe->SetTotalSize( iReceivedMessage->ContentLengthL() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NotifyUpperLayerL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::NotifyUpperLayerLD( CUpnpHttpMessage* aMessage )
+    {
+    LOGS2( "%i, CUpnpHttpSession::NotifyUpperLayerL %i", iId,
+            aMessage->Error( ) );
+    CleanupStack::PushL( aMessage );
+
+    aMessage->SetSessionId( iId );
+
+    if ( iPendingRequest )
+        {
+        aMessage->SetPendingRequest( iPendingRequest );
+        }
+    aMessage->SetSenderPathL( *iSenderPath );
+
+    if ( aMessage->Method().FindC( KHttp11WithoutSpace ) == 0
+            || aMessage->Method().FindC( KHttp10 ) == 0 )
+        {
+        aMessage->SetDestinationPathL( *iDestinationPath );
+        }
+    else
+        {
+        TPtrC8 path = aMessage->SenderPathFromHeader();
+        aMessage->SetDestinationPathL( path );
+        }
+
+    aMessage->SetType( iRequestType );
+    aMessage->SetRetryCounter( iRetryCounter );
+
+    iDisconnectNotification = EFalse;
+    aMessage->SetOutFilenameL( *iOutFilename );
+    CleanupStack::Pop( aMessage );
+    iServer->ToReceiveStackD( aMessage );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::IsValidMessage
+//
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpSession::THttpInvalidMessage CUpnpHttpSession::IsValidMessage(
+    CUpnpHttpMessage* aMsg )
+    {
+    // Checking method. METHOD NAMES ARE CASE SENSITIVE,
+    // so checking that method is OK.
+    // http://www.w3.org/Protocols/HTTP/Methods.html
+    if ( aMsg->Method().Find( KHttpGet() ) != 0 && aMsg->Method().Find(
+        KHttpPost() ) != 0 && aMsg->Method().Find( KHttpHead() ) != 0
+            && aMsg->Method().Find( KHttpOptions() ) != 0
+            && aMsg->Method().Find( KHttpPut() ) != 0 && aMsg->Method().Find(
+        KHttpDelete() ) != 0 && aMsg->Method().Find( KHttpTrace() ) != 0
+            && aMsg->Method().Find( KHttpConnect() ) != 0
+            && aMsg->Method().Find( KHttp11WithoutSpace() ) != 0
+            && aMsg->Method().Find( KHttp10() ) != 0 && aMsg->Method().Find(
+        UpnpGENA::KGenaSubscribe() ) != 0 && aMsg->Method().Find(
+        UpnpGENA::KGenaUnSubscribe() ) != 0 && aMsg->Method().Find(
+        UpnpGENA::KGenaNotify() ) != 0 )
+        {
+        return EUnknownMethod;
+        }
+    return EMessageOk;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::FileAccess
+//
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpFileAccess* CUpnpHttpSession::FileAccess()
+    {
+    return iFileServe;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::OverwriteExisting
+//
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpSession::OverwriteExisting()
+    {
+    return iOverwriteExisting;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::Offset
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::Offset()
+    {
+    return iOffset;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::Length
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::Length()
+    {
+    return iLength;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::SaveAtOffset
+//
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpSession::SaveAtOffset()
+    {
+    return iSaveAtOffset;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::ServerPort
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::ServerPort()
+    {
+    return iServer->ServerPort();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::CheckConnectionClose
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::CheckConnectionCloseL()
+    {
+    LOGS1( "%i, CUpnpHttpSession::CheckConnectionCloseL", iId );
+
+    if ( iReceivedMessage )
+        {
+        if ( iReceivedMessage->IsHeaderReady()
+                && iReceivedMessage->UsesConnectionClose() )
+            {
+            TPtrC8 buffer = iReceivedMessage->Content();
+
+            CUpnpHttpMessage* msg = NULL;
+            TInt err;
+                TRAP( err, msg = CUpnpHttpMessage::NewL( buffer, RemoteHost( ),
+                                iId ) );
+            CleanupStack::PushL( msg );
+            // If parsing error occurs, or 'stop transfer' occurs during export from other MS to this MS
+            // and the resource [file] isn't completely downloaded -> don't notify upper layers
+            if ( err < KErrNone || (err == KErrNone
+                    && (iReceivedMessage->Method().Find( KHttpPost ) == 0)
+                    && !iReceivedMessage->IsReadyL()) )
+                {
+                LOGS1H(
+                        iHandle,
+                        "%i, CUpnpHttpSession::CheckConnectionCloseL - parsing error",
+                        iId );
+
+                iReceivedMessage->RemoveL( buffer.Length() );
+                StartDisconnect();
+                CleanupStack::PopAndDestroy( msg );
+                return;
+                }
+
+            msg->SetInFilenameL( *iInFilename );
+            if ( !iReceivedMessage->IsToFile()
+                    || (iReceivedMessage->IsToFile() && iFileServe
+                            && iFileServe->FileExist()) )
+                {
+                CleanupStack::Pop( msg );
+                NotifyUpperLayerLD( msg );
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy( msg );
+                }
+            iPendingRequest = NULL;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::NotifyUpperLayersOnPostL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::NotifyUpperLayersOnPostL()
+    {
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseOkL(
+        RemoteHost() );
+
+    CleanupStack::PushL( msg );
+
+    CUpnpHttpHeaderList* List = NULL;
+    List = msg->HeaderList();
+
+    CUpnpHttpHeader* hdr = List->First();
+
+	if(hdr != NULL)
+	{
+		HBufC8* newHeader = NULL;
+		newHeader = HBufC8::NewLC( KTransferPending801().Length() );
+		newHeader->Des().Zero();
+		newHeader->Des().Append( KTransferPending801() );
+
+		hdr->SetNameL( *newHeader );
+
+		CleanupStack::PopAndDestroy( newHeader );
+	}
+    msg->SetOutFilenameL( *iOutFilename );
+    CleanupStack::Pop( msg );
+    NotifyUpperLayerLD( msg );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::PostingFileCompleteL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::PostingFileCompleteL()
+    {
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseOkL(
+        RemoteHost() );
+    CleanupStack::PushL( msg );
+    msg->SetOutFilenameL( *iOutFilename );
+
+    CleanupStack::Pop( msg );
+    NotifyUpperLayerLD( msg );
+    }
+
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::IsMsgReady
+//
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpSession::IsMsgReady()
+    {
+    TBool ret = EFalse;
+
+    if ( iReceivedMessage )
+        {
+        TRAPD( err, ret = iReceivedMessage->IsReadyL( ) );
+
+        if ( err != KErrNone )
+            return EFalse;
+
+        return ret;
+        }
+    else
+        return EFalse;
+    }
+
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::HttpServer()
+// Returns pointer to the CUpnpHttpServer object
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpServer* CUpnpHttpSession::HttpServer()
+    {
+    return iServer;
+    }
+
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::FileTransferReaderDoneL()
+// Callback from file transfer reader
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::FileTransferReaderDoneL()
+    {
+    LOGS1( "%i, CUpnpHttpSession::FileTransferReaderDoneL", iId );
+    //notify import completed to upper layers
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+        iAddr, EHttp200Ok );
+    CleanupStack::PushL( msg );
+    msg->SetType( EImportComplete );
+    msg->SetSessionId( Id() );
+    //setting it only for a POST request
+    msg->SetDestinationPathL( KNullDesC8 );
+    CleanupStack::Pop( msg );
+    iServer->ToReceiveStackD( msg );
+
+    TPtrC8 headers = iReceivedMessage->Headers();
+    //original message received from the remote MS
+    CUpnpHttpMessage* original = CUpnpHttpMessage::NewL( (TDesC8&) headers,
+        RemoteHost(), iId );
+    CleanupStack::PushL( original );
+    original->SetInFilenameL( *iInFilename );
+    delete iFileServe;
+    iFileServe = NULL;
+    //notify POST is finished
+    //prepare reply 200 Ok for the remote MS
+    CUpnpHttpMessage* reply = RUpnpHttpMessageFactory::HttpResponseOkL(
+        original );
+    CleanupStack::PushL( reply );
+    reply->AddPairL( UpnpHTTP::KHdrServer(), iServer->ServerDescription() );
+    reply->AddPairL( UpnpHTTP::KConnection(), UpnpHTTP::KClose() );
+    HBufC8* sendBuf = reply->ToStringL();
+    CleanupStack::PopAndDestroy( reply );
+    CleanupStack::Pop( original );
+    //inform the upper layer
+    iServer->ToReceiveStackD( original );
+    CleanupStack::PushL( sendBuf );
+    //send reply to the client
+    WriteL( *sendBuf );
+    CleanupStack::PopAndDestroy( sendBuf );
+
+    ResetSettingsL();
+
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::FileTransferReaderDoneL()
+// Callback from file transfer reader
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::FileTransferReaderErrorL( TInt aError )
+    {
+    LOGS1( "CUpnpHttpSession::FileTransferReaderErrorL %d", aError );
+    if ( iFileServe )
+        iFileServe->DeleteFile();
+    NotifyErrorL( aError );
+    if ( aError > 0 )
+        aError = -aError;
+    TInt httpError = MatchHttpError( aError );
+    if ( httpError != KErrNone )
+        {// If we act as a server side
+        ResponseErrorL( httpError );
+        ShutdownStop();
+        return;
+        }
+    ResetSettingsL();
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::ResetSettingsL()
+// Callback from file transfer reader
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::ResetSettingsL()
+
+    {
+    LOGS1( "%d, CUpnpHttpSession::ResetSettingsL", iId );
+    iContinuedMessageDownload = EFalse;
+    iHeadersCompleted = EFalse;
+
+    delete iFileServe;
+    iFileServe = NULL;
+
+    delete iReceivedMessage;
+    iReceivedMessage = NULL;
+
+    delete iInFilename;
+    iInFilename = NULL;
+    iInFilename = HBufC8::NewMaxL( 0 );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpSession::FileTransferWriterDoneL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::FileTransferWriterDoneL()
+    {
+
+    LOGS1( "%i, CUpnpHttpSession::FileTransferWriterDoneL()", iId );
+
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL(
+        iAddr, EHttp200Ok );
+    CleanupStack::PushL( msg );
+    msg->SetType( EExportComplete );
+
+    msg->SetSessionId( Id() );
+
+    CleanupStack::Pop( msg );
+    iServer->ToReceiveStackD( msg );
+
+    delete iFileServe;
+    iFileServe = NULL;
+
+    iSessionNeedsErrorReply = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::FileTransferWriterHandleMoreL()
+// Callback from file transfer writer
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::FileTransferWriterHandleMoreL()
+
+    {
+    LOGS1( "%i, CUpnpHttpSession::FileTransferWriterHandleMoreL()",
+            iId );
+    if ( FileTransferWriter() )
+        FileTransferWriter()->Reset();
+
+    if ( !IsPersistentConnection() )
+        {
+        StartClosingSession();
+        return;
+        }
+
+    while ( iPendingRequests->Count() > 0 )
+        {
+        iSessionNeedsErrorReply = ETrue;
+
+        CUpnpHttpMessage* request = (*iPendingRequests)[0];
+        iPendingRequests->Remove( 0 );
+        CleanupStack::PushL( request );
+        TInt error = PrepareToServeFileL( request );
+        CleanupStack::PopAndDestroy( request );
+
+        if ( error )
+            {
+            NotifyErrorL( error );
+            if ( error > 0 )
+                error = -error;
+            TInt httpError = MatchHttpError( error );
+            if ( httpError != KErrNone )
+                {// If we act as a server side
+                if ( iSessionNeedsErrorReply )
+                    {
+                    ResponseErrorL( httpError );
+                    }
+                }
+
+            if ( !IsPersistentConnection() )
+                {
+                StartClosingSession();
+                }
+            }
+        else
+            {
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::CheckSessionPersistence
+// Checks if message contains CONNECTION:CLOSE
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::CheckSessionPersistence( CUpnpHttpMessage* aMsg )
+    {
+    if ( aMsg->GetHeaderValue( UpnpHTTP::KConnection() ).FindC(
+        UpnpHTTP::KClose() ) >= 0 || aMsg->RequestHTTPVersion() == KHttp10() )
+        {
+        iIsPersistent = EFalse;
+        }
+    else
+        {
+        iIsPersistent = ETrue;
+        }
+
+    if ( !IsPersistentConnection() )
+        {
+        iSessionKeepAlive = EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::DestroyIt()
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpSession::DestroyIt( CUpnpTcpSession* aSession )
+    {
+    iServer->DeleteSession( aSession );
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::PrepareRangeHeaderL()
+//
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpSession::PrepareRangeHeaderL( CUpnpHttpMessage* aMsg,
+    TBool aServingOutFileName, TInt aFileSize,
+    CUpnpHttpServerTransaction &aTransaction, TInt& aRangeStatus, TInt& aStartPos, TInt& aEndPos )
+    {
+    // Generating headers
+    aStartPos = KErrNotFound;
+    aEndPos = KErrNotFound;
+
+    // Check if there is a Range header in request and if it's correct
+    CUpnpRangeHeaderParser* rangeParser = CUpnpRangeHeaderParser::NewLC(
+        aTransaction, aStartPos, aEndPos );
+    aRangeStatus = rangeParser->ParseRangeL( aMsg, aFileSize );
+    CleanupStack::PopAndDestroy( rangeParser );
+
+    if ( aRangeStatus != EHttpOk )
+        {
+        if ( aRangeStatus <= -EHttpBadRequest )
+            {
+            return aRangeStatus;
+            }
+        else if ( aRangeStatus == EHttpNoContent )
+            {
+            return KErrNone;
+            }
+        }
+    else
+        {
+        // Serve whole file
+        if ( !aServingOutFileName )
+            {
+            // If OutFilename() was set in msg
+            TBuf8<2 * KMaxIntegerLength> sizeBuffer;
+            sizeBuffer.Num( aFileSize );
+            aTransaction.AddResponseHeaderL( KNullDesC8(), UpnpHTTP::KHTTPOk() );
+            aTransaction.AddResponseHeaderL( UpnpHTTP::KHdrContentLength(), sizeBuffer );
+            }
+        else
+            {
+            // If file path was extracted from header
+            HBufC8* tempBuffer = aMsg->HeadersToStringL();
+            CleanupStack::PushL( tempBuffer );
+            aTransaction.AddResponseHeaderL( KNullDesC8(), *tempBuffer );
+            CleanupStack::PopAndDestroy( tempBuffer );
+            }            
+        }
+
+    return  KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+//  CUpnpHttpSession::PrepareRelativeUriL
+//
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CUpnpHttpSession::PrepareRelativeUriL( const TDesC8& aUri )
+    {
+    TInetAddr resourceServerAddress;
+    iServer->ServerAddress( resourceServerAddress );
+    TInt portNo = iServer->ServerPort();
+    
+    TBuf<KMaxName> addrTmp;
+    resourceServerAddress.Output( addrTmp );
+    HBufC8* addr = UpnpString::FromUnicodeL( addrTmp );
+    CleanupStack::PushL( addr );
+    
+    TBuf8<KMaxName> port;
+    port.Num( portNo );
+    
+    TInt addrLength = UpnpHTTP::KHTTPUrl().Length() +  addr->Length( ) + UpnpString::KColon().Length( ) + port.Length( );
+    HBufC8* temp = HBufC8::NewLC( addrLength );
+    TPtr8 tempPtr( temp->Des() );
+    tempPtr.Append(  UpnpHTTP::KHTTPUrl );
+    tempPtr.Append( *addr );
+    tempPtr.Append( UpnpString::KColon );
+    tempPtr.Append( port );
+
+    CleanupStack::Pop( temp );
+    CleanupStack::PopAndDestroy( addr );
+    
+    if ( aUri.Find( *temp ) == 0  )
+        {
+        delete temp;
+        return aUri.Mid( addrLength );
+        }
+    
+    delete temp;
+    return aUri; 
+    }
+
+// End Of File