upnp/upnpstack/dlnawebserver/src/upnptcpsessionwriter.cpp
changeset 0 f5a58ecadc66
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:  CUpnpTcpSessionWriter is a class responsible for 
       
    15 *                   asynchronous writing to a socket owned by CUpnpTcpSession.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "upnptcpsession.h"
       
    22 #include "upnptcpsessionwriter.h" 
       
    23 #define KLogFile _L("DLNAWebServer.txt")
       
    24 #include "upnpcustomlog.h"
       
    25 
       
    26 
       
    27 class CUpnpTcpWriteRequest : public CBase
       
    28   	{
       
    29 public:
       
    30   	static CUpnpTcpWriteRequest* NewL( const TDesC8& aBuffer )
       
    31 		    {
       
    32 		    CUpnpTcpWriteRequest* self = new (ELeave) CUpnpTcpWriteRequest();
       
    33 		    CleanupStack::PushL( self );
       
    34 		    self->ConstructL( aBuffer );
       
    35 		    CleanupStack::Pop();
       
    36 		
       
    37 		    return self;
       
    38 		    }
       
    39     
       
    40 private:
       
    41 	  CUpnpTcpWriteRequest() {}
       
    42 	  void ConstructL( const TDesC8& aBuffer )
       
    43 		    {
       
    44 		    iBuffer.CreateL( aBuffer );
       
    45 		    }
       
    46     
       
    47 public:
       
    48   	TDesC8& Buffer()
       
    49 		    {
       
    50 		    return iBuffer;
       
    51 		    }
       
    52   
       
    53 	  ~CUpnpTcpWriteRequest()
       
    54 		    {
       
    55 		    iBuffer.Close();
       
    56 		    }
       
    57     
       
    58 private:
       
    59   	RBuf8 iBuffer;
       
    60   	};
       
    61   
       
    62 // ======== MEMBER FUNCTIONS ========
       
    63 
       
    64 // ---------------------------------------------------------------------------
       
    65 // CUpnpTcpSessionWriter::NewL
       
    66 // Factory method.
       
    67 // ---------------------------------------------------------------------------
       
    68 //
       
    69 CUpnpTcpSessionWriter* CUpnpTcpSessionWriter::NewL( CUpnpTcpSession& aSession,
       
    70                                                     RSocket& aSocket,
       
    71                                                     TThreadPriority aPriority )
       
    72     {
       
    73     CUpnpTcpSessionWriter* self = new ( ELeave ) 
       
    74             CUpnpTcpSessionWriter( aSession, aSocket, aPriority );
       
    75     CleanupStack::PushL( self );
       
    76     self->ConstructL();
       
    77     CleanupStack::Pop( self );
       
    78     return self;
       
    79     }
       
    80     
       
    81 // ---------------------------------------------------------------------------
       
    82 // CUpnpTcpSessionWriter::CUpnpTcpSessionWriter
       
    83 // C++ constructor.
       
    84 // ---------------------------------------------------------------------------
       
    85 //
       
    86 CUpnpTcpSessionWriter::CUpnpTcpSessionWriter( CUpnpTcpSession& aSession,
       
    87                                               RSocket& aSocket, 
       
    88                                               TThreadPriority aPriority )
       
    89     :CActive( aPriority ),
       
    90     iSocket( aSocket ),
       
    91     iSession( aSession ),
       
    92     iInitialPriority( aPriority )
       
    93     {
       
    94     LOGS1( "%i, CUpnpTcpSessionWriter::CUpnpTcpSessionWriter", iSession.Id() );
       
    95     }
       
    96 
       
    97 // ---------------------------------------------------------------------------
       
    98 // CUpnpTcpSessionReader::TcpConstructL
       
    99 // Two-phased constructor
       
   100 // constructor that can leave. Used from derived classes.
       
   101 // ---------------------------------------------------------------------------
       
   102 //
       
   103 void CUpnpTcpSessionWriter::ConstructL()
       
   104     {
       
   105     CActiveScheduler::Add( this );
       
   106     iState = ENotConnected;
       
   107     iRetryWrite = CUpnpRetryWrite::NewL( iSession, iSocket, this, (TThreadPriority)Priority() );
       
   108     }
       
   109     
       
   110 // ---------------------------------------------------------------------------
       
   111 // CUpnpTcpSessionReader::~CUpnpTcpSessionReader
       
   112 // Destructor.
       
   113 // ---------------------------------------------------------------------------
       
   114 //
       
   115 CUpnpTcpSessionWriter::~CUpnpTcpSessionWriter()
       
   116     {
       
   117     LOGS1( "%i, CUpnpTcpSessionWriter::~CUpnpTcpSessionWriter", iSession.Id() );
       
   118     
       
   119     Cancel();
       
   120     iState = EDisconnected;
       
   121     
       
   122     iWriteRequestList.ResetAndDestroy();
       
   123     iWriteRequestList.Close();
       
   124   
       
   125     iSendBuffer.Close();
       
   126 
       
   127     delete iRetryWrite;
       
   128     }
       
   129 
       
   130 // ---------------------------------------------------------------------------
       
   131 // CUpnpTcpSessionWriter::IssueWriteL
       
   132 // Issues writing request if session is connected and the socket is not 
       
   133 // already sending. If metioned conditions are not met then it queues the request.
       
   134 // ---------------------------------------------------------------------------
       
   135 //
       
   136 void CUpnpTcpSessionWriter::IssueWriteL( const TDesC8& aBuffer )
       
   137     {
       
   138     LOGS1( "%i, CUpnpTcpSessionWriter::IssueWriteL(TDesC8&)", iSession.Id() );
       
   139     
       
   140     // Don't do anything because socket is already closed or we are writing already.
       
   141     if( iState == EDisconnected || (iSession.DownloadOngoing() ) 
       
   142         	|| (iSession.ShuttingDown() && iState != ENotConnected) )
       
   143         return;
       
   144     
       
   145     // If session not connected yet or is already sending then queue the write request
       
   146     if ( iState == ENotConnected || iState == EWriting )
       
   147         {
       
   148         CUpnpTcpWriteRequest* req = CUpnpTcpWriteRequest::NewL( aBuffer );
       
   149         CleanupStack::PushL(req);
       
   150         User::LeaveIfError(iWriteRequestList.Append( req ));
       
   151         CleanupStack::Pop();
       
   152         
       
   153         LOGS2(  "%i, CUpnpTcpSessionWriter::IssueWriteL - queue size=%i,"
       
   154                           , iSession.Id(), iWriteRequestList.Count() );
       
   155         return;
       
   156         }
       
   157     
       
   158     LOGS2( "%i, CUpnpTcpSessionWriter::IssueWriteL queue size=%i"
       
   159                      , iSession.Id() , iWriteRequestList.Count() );
       
   160                      
       
   161     // If session already connected then just prepare sending buffer and request 
       
   162     // send from socket
       
   163 
       
   164     iSendBuffer.Close();
       
   165     iSendBuffer.CreateL( aBuffer );
       
   166     
       
   167     /*if (Priority() == iInitialPriority)       
       
   168         SetPriority( iInitialPriority - 5);       
       
   169     else 
       
   170         SetPriority( iInitialPriority); */
       
   171         
       
   172     Deque();
       
   173     CActiveScheduler::Add(this);  
       
   174     
       
   175     iSocket.Write( iSendBuffer, iStatus );
       
   176     iState = EWriting;  
       
   177     
       
   178     SetActive();
       
   179     }
       
   180     
       
   181 // ---------------------------------------------------------------------------
       
   182 // CUpnpTcpSessionWriter::SessionConnected
       
   183 // Informs writer if session is connected. If it is then writer checks if there
       
   184 // are queued write requests. If there are any then it issues writing.
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 void CUpnpTcpSessionWriter::SessionConnected( TBool aConnected )
       
   188     {
       
   189     LOGS2( "%i, CUpnpTcpSessionWriter::SessionConnected(),aConnected %i"
       
   190     		, iSession.Id() , aConnected );
       
   191     if( aConnected && iState == ENotConnected )
       
   192         {
       
   193         iState = EWaiting;
       
   194         TRAP_IGNORE( SendNextWriteRequestL() );
       
   195         }
       
   196     else if( !aConnected && iState != ENotConnected )
       
   197         {
       
   198         Cancel();
       
   199         iState = EDisconnected;
       
   200         }
       
   201     } 
       
   202     
       
   203 // ---------------------------------------------------------------------------
       
   204 // CUpnpTcpSessionWriter::HasWriteRequestsToSend
       
   205 // Returns true if there are any write requests queued.
       
   206 // ---------------------------------------------------------------------------
       
   207 //
       
   208 TBool CUpnpTcpSessionWriter::HasWriteRequestsToSend()
       
   209     {
       
   210     return ( iWriteRequestList.Count() > 0 );
       
   211     }
       
   212 
       
   213 // ---------------------------------------------------------------------------
       
   214 // CUpnpTcpSessionWriter::IsWriting
       
   215 // Returns true if writer is writing data to the socket at the moment.
       
   216 // ---------------------------------------------------------------------------
       
   217 //          
       
   218 TBool CUpnpTcpSessionWriter::IsWriting()
       
   219   {
       
   220   return iState == EWriting;    
       
   221   }
       
   222   
       
   223 // ---------------------------------------------------------------------------
       
   224 // CUpnpTcpSessionWriter::DoCancel
       
   225 // From class CActive
       
   226 // Cancels issued writing request.
       
   227 // ---------------------------------------------------------------------------
       
   228 //
       
   229 void CUpnpTcpSessionWriter::DoCancel()
       
   230     {
       
   231     LOGS1( "%i, CUpnpTcpSessionWriter::DoCancel", iSession.Id() );
       
   232     
       
   233     // Cancel asychronous write request
       
   234     iState = EWaiting;
       
   235     }
       
   236     
       
   237 // ---------------------------------------------------------------------------
       
   238 // CUpnpTcpSessionWriter::RunL
       
   239 // From class CActive
       
   240 // Function called when issued writing is completed. Function checks if there
       
   241 // are any write requests left to send and if there are then it issues writing.
       
   242 // If queue is empty then function informs upper layer that writing is completed.
       
   243 // ---------------------------------------------------------------------------
       
   244 //
       
   245 void CUpnpTcpSessionWriter::RunL()
       
   246     {
       
   247     LOGS2( "%i, CUpnpTcpSessionWriter::RunL(), iStatus %i", 
       
   248     		iSession.Id() , iStatus.Int() );
       
   249     
       
   250     // Active object request complete handler
       
   251     if ( iStatus == KErrNone )
       
   252         {
       
   253         switch( iState )
       
   254             {
       
   255             // Character has been written to socket
       
   256             case EWriting:
       
   257                 
       
   258                 if (Priority() == iInitialPriority)       
       
   259                     SetPriority( iInitialPriority + 5);       
       
   260                 else 
       
   261                     SetPriority( iInitialPriority); 
       
   262                 
       
   263                 // Change state because write request is finished already
       
   264                 iState = EWaiting;
       
   265                 if( HasWriteRequestsToSend() )
       
   266                     SendNextWriteRequestL();
       
   267                 else
       
   268                     iSession.WritingCompletedL();
       
   269                 break;
       
   270             
       
   271             default:
       
   272                 LOGS2( "%i, PANIC: CUpnpTcpSessionWriter::RunL, %i",
       
   273                 		iSession.Id() , iState );
       
   274                 User::Panic( _L("Writer::RunL"), iState );
       
   275                 break;
       
   276             };
       
   277         }
       
   278     else
       
   279         {
       
   280 			if( iState == EWriting && (iStatus.Int() == KErrNoMemory || iStatus.Int() == KErrNotReady ) )
       
   281 			{
       
   282 				iRetryWrite->IssueWriteRetry();
       
   283        		}
       
   284         else
       
   285 	        {
       
   286 
       
   287 				// Error: pass it up to session
       
   288 				iState = EWaiting;
       
   289 				iSession.HandleErrorL( iStatus.Int() );
       
   290 			}
       
   291         }
       
   292     }
       
   293 // -----------------------------------------------------------------------------
       
   294 // CUpnpTcpSessionWriter::RunError
       
   295 // RunError is called when RunL leaves.
       
   296 // -----------------------------------------------------------------------------
       
   297 //
       
   298 TInt CUpnpTcpSessionWriter::RunError( TInt aError )
       
   299     {
       
   300     LOGS2( "%i, CUpnpTcpSessionWriter::RunError %d"
       
   301     		, iSession.Id() , aError);
       
   302     return KErrNone;
       
   303     }
       
   304 
       
   305 
       
   306 // ---------------------------------------------------------------------------
       
   307 // CUpnpTcpSessionWriter::SendNextWriteRequestL
       
   308 // Function checks if there are any write requests left and if there are then
       
   309 // issues writing and removes this request from queue.
       
   310 // ---------------------------------------------------------------------------
       
   311 //
       
   312 void CUpnpTcpSessionWriter::SendNextWriteRequestL()
       
   313     {
       
   314     LOGS2( "%i, CUpnpTcpSessionWriter::SendNextWriteRequest(), iState %i",
       
   315     		iSession.Id() , iState );
       
   316     switch( iState )
       
   317         {
       
   318         case EWaiting:
       
   319             // Write queued request
       
   320             if ( iWriteRequestList.Count() > 0 )
       
   321             		{
       
   322                 CUpnpTcpWriteRequest* req = iWriteRequestList[0];
       
   323                 if ( req )
       
   324                     {
       
   325                     iWriteRequestList.Remove(0);
       
   326                     iWriteRequestList.Compress();
       
   327                     CleanupStack::PushL( req );
       
   328                     IssueWriteL( req->Buffer() );
       
   329                     CleanupStack::PopAndDestroy( req );
       
   330                     }
       
   331             }
       
   332             break;
       
   333 
       
   334         case ENotConnected:
       
   335         case EDisconnected:
       
   336             LOGS2( "%i, PANIC: CUpnpTcpSessionWriter::SendNextWriteRequest, %i",
       
   337             		iSession.Id() , iState );
       
   338             User::Panic( _L("SendNext::ENotConnected or EDisconnected"), iState );
       
   339             break;
       
   340         }
       
   341     }  
       
   342 
       
   343 // ---------------------------------------------------------------------------
       
   344 // CUpnpTcpSessionWriter::RetryWriteFailL
       
   345 //    
       
   346 // ---------------------------------------------------------------------------
       
   347 //    
       
   348 void CUpnpTcpSessionWriter::RetryWriteFailL( TInt aError )
       
   349 	{
       
   350 	// Error: pass it up to session
       
   351 	iSession.HandleErrorL( aError );
       
   352 	iState = EWaiting;
       
   353 	}
       
   354 
       
   355 // ---------------------------------------------------------------------------
       
   356 // CUpnpTcpSessionWriter::RetryWriteSucceed
       
   357 //    
       
   358 // ---------------------------------------------------------------------------
       
   359 //    
       
   360 void CUpnpTcpSessionWriter::RetryWriteSucceed()
       
   361 	{
       
   362     if ( iSendBuffer.Length() == 0 ) return;
       
   363     
       
   364     Deque();
       
   365     CActiveScheduler::Add(this);  
       
   366     
       
   367     iSocket.Write( iSendBuffer, iStatus );
       
   368     iState = EWriting;         
       
   369     
       
   370     SetActive();
       
   371 	}
       
   372 
       
   373 // ---------------------------------------------------------------------------
       
   374 // CUpnpTcpSessionWriter::IsRetrying
       
   375 //    
       
   376 // ---------------------------------------------------------------------------
       
   377 //    
       
   378 TBool CUpnpTcpSessionWriter::IsRetrying()
       
   379 	{
       
   380 	return (iRetryWrite->IsStarted());
       
   381 	}
       
   382 
       
   383 //  End of File