applayerpluginsandutils/httpprotocolplugins/httpclient/chttprequestbatcher.cpp
changeset 0 b16258d2340f
child 5 337070b4fa18
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <x509cert.h>
       
    17 
       
    18 #include "chttprequestbatcher.h"
       
    19 
       
    20 
       
    21 const TInt KBatchingTimeoutMicroSeconds = 100000;
       
    22 
       
    23 
       
    24 CHttpRequestBatcher* CHttpRequestBatcher::NewL(MOutputStream& aOutputStream, const TInt aBufferSize)
       
    25 	{
       
    26 	CHttpRequestBatcher* self = new (ELeave) CHttpRequestBatcher(aOutputStream, aBufferSize);
       
    27 	CleanupStack::PushL(self);
       
    28 	self->ConstructL();
       
    29 	CleanupStack::Pop(self);
       
    30 	return self;
       
    31 	}
       
    32 
       
    33 CHttpRequestBatcher::CHttpRequestBatcher(MOutputStream& aOutputStream, const TInt aBufferSize)
       
    34 : CActive(CActive::EPriorityStandard + 1), iDataToSend(TPtr8(NULL, 0)), iExcessData(TPtrC8(NULL, 0)), iMaxBufferSize(aBufferSize)
       
    35 	{
       
    36 	__FLOG_OPEN("http", "httpclienthandler.txt");
       
    37 
       
    38 	CActiveScheduler::Add(this);
       
    39 	iOutputStream = &aOutputStream;
       
    40 	iOutputStream->Bind(*this);
       
    41 
       
    42 	iFuncPtr = &CHttpRequestBatcher::SendRequestImmediatelyL;
       
    43 	}
       
    44 
       
    45 void CHttpRequestBatcher::ConstructL()
       
    46 	{
       
    47 	iBuffer = HBufC8::NewL(iMaxBufferSize);
       
    48 	iDataToSend.Set(iBuffer->Des());
       
    49 
       
    50 	iTimer.CreateLocal();
       
    51 	iTimerCompleted = EFalse;
       
    52 
       
    53 	}
       
    54 
       
    55 
       
    56 CHttpRequestBatcher::~CHttpRequestBatcher()
       
    57 	{
       
    58 	Cancel();
       
    59 	delete iBuffer;
       
    60 	iTimer.Close();
       
    61 
       
    62 	__FLOG_CLOSE;
       
    63 	}
       
    64 
       
    65 
       
    66 void CHttpRequestBatcher::SendRequestImmediatelyL(const TDesC8& aBuffer)
       
    67 	{
       
    68 #if defined (_DEBUG) && defined (_LOGGING)
       
    69 		__FLOG_0(_T8("!! Send the first request i.e. not batching"));
       
    70 #endif
       
    71 
       
    72 	iOutputStream->SendDataReqL(aBuffer);
       
    73 	}
       
    74 
       
    75 void CHttpRequestBatcher::SendRequestsBatchedL(const TDesC8& aBuffer)
       
    76 	{
       
    77 	StartTimer();
       
    78 
       
    79 	BatchRequestsL(aBuffer);
       
    80 	}
       
    81 
       
    82 void CHttpRequestBatcher::BatchRequestsL(const TDesC8& aBuffer)
       
    83 	{
       
    84 	if (iTimerCompleted)
       
    85 		iExcessData.Set(aBuffer);
       
    86 
       
    87 	else if ((aBuffer.Length() + iDataToSend.Length()) < iMaxBufferSize)
       
    88 		{
       
    89 		iDataToSend.Append(aBuffer);
       
    90 		
       
    91 		// Buffer is not yet full, so request observer to send more data
       
    92 		iObserver->SendDataCnfL();
       
    93 		}
       
    94 	else
       
    95 		{
       
    96 		TInt pos = iMaxBufferSize - iDataToSend.Length();
       
    97 
       
    98 		// Fill up the buffer
       
    99 		iDataToSend.Append(aBuffer.Left(pos));
       
   100 
       
   101 		// Cancel the timer
       
   102 		Cancel();
       
   103 
       
   104 #if defined (_DEBUG) && defined (_LOGGING)
       
   105 		__FLOG_0(_T8("!! Buffer has been filled - cancel timer and send batched requests now"));
       
   106 #endif
       
   107 
       
   108 		// Send the request with a filled-up buffer
       
   109 		iOutputStream->SendDataReqL(iDataToSend);
       
   110 
       
   111 		// Save the excess data from this request
       
   112 		iExcessData.Set(aBuffer.Mid(pos));
       
   113 		}
       
   114 	}
       
   115 
       
   116 void CHttpRequestBatcher::StartTimer()
       
   117 	{
       
   118 	if(!IsActive())
       
   119 		{
       
   120 #if defined (_DEBUG) && defined (_LOGGING)
       
   121 		__FLOG_0(_T8("!! Start the batching timer"));
       
   122 #endif
       
   123 
       
   124 		SetActive();
       
   125 		iTimer.After(iStatus, KBatchingTimeoutMicroSeconds);
       
   126 		}
       
   127 	}
       
   128 
       
   129 
       
   130 /*
       
   131  *	Methods from MOutputStream
       
   132  */
       
   133 
       
   134 void CHttpRequestBatcher::Bind(MOutputStreamObserver& aObserver)
       
   135 	{
       
   136 	// Bind to the output stream observer
       
   137 	iObserver = &aObserver;
       
   138 	}
       
   139 
       
   140 void CHttpRequestBatcher::SendDataReqL(const TDesC8& aBuffer)
       
   141 	{
       
   142 	// Call the appropriate function depending on what the function pointer has been set to.
       
   143 	// For the first request, the pointer will be set to the SendRequestImmediately() function.
       
   144 	// For subsequent requests, i.e. when batching, the pointer will be set to the
       
   145 	// SendRequestsBatched() function.
       
   146 
       
   147 	(*this.*iFuncPtr)(aBuffer);
       
   148 	}
       
   149 
       
   150 void CHttpRequestBatcher::ShutdownReq()
       
   151 	{
       
   152 	iOutputStream->ShutdownReq();
       
   153 	}
       
   154 
       
   155 void CHttpRequestBatcher::SecureClientReq(const TDesC8& aHostName)
       
   156 	{
       
   157 	iOutputStream->SecureClientReq(aHostName);
       
   158 	}
       
   159 
       
   160 void CHttpRequestBatcher::Close()
       
   161 	{
       
   162 	iOutputStream->Close();
       
   163 	}
       
   164 
       
   165 const CX509Certificate* CHttpRequestBatcher::ServerCert()
       
   166  	{
       
   167 	return iOutputStream->ServerCert();
       
   168  	}
       
   169 	
       
   170 TInt CHttpRequestBatcher::CipherSuite(TDes8& aCipherSuite)
       
   171 	{
       
   172 	return iOutputStream->CipherSuite(aCipherSuite);
       
   173 	}
       
   174 
       
   175 void CHttpRequestBatcher::MOutputStream_Reserved()
       
   176 	{
       
   177 	User::Invariant();
       
   178 	}
       
   179 
       
   180 void CHttpRequestBatcher::Reset ()
       
   181 	{
       
   182 	iOutputStream->Reset ();
       
   183 	}
       
   184 
       
   185 /*
       
   186  *	Methods from MOutputStreamObserver
       
   187  */
       
   188 
       
   189 void CHttpRequestBatcher::SendDataCnfL()
       
   190 	{
       
   191 	// If this is the first request send a confirmation to the observer that the data
       
   192 	// has been sent and then set the function pointer to the SendRequestBatched() method.
       
   193 	if (iFuncPtr == &CHttpRequestBatcher::SendRequestImmediatelyL)
       
   194 		{
       
   195 #if defined (_DEBUG) && defined (_LOGGING)
       
   196 		__FLOG_0(_T8("!! Received conf back for first request i.e. not batching"));
       
   197 #endif
       
   198 
       
   199 		iObserver->SendDataCnfL();
       
   200 		iFuncPtr = &CHttpRequestBatcher::SendRequestsBatchedL;
       
   201 		}
       
   202 
       
   203 	// If the timer did not complete then by implication a filled-up buffer was sent in the request.
       
   204 	else if (!iTimerCompleted)
       
   205 		{
       
   206 #if defined (_DEBUG) && defined (_LOGGING)
       
   207 		__FLOG_0(_T8("!! Received conf back for batched requests"));
       
   208 #endif
       
   209 
       
   210 		iDataToSend.Zero();
       
   211 		HandleExcessDataL();
       
   212 		}
       
   213 	else	// Timer did complete
       
   214 		{
       
   215 		iDataToSend.Zero();
       
   216 
       
   217 		// Check for any requests that may have been sent by the observer after the RunL fired
       
   218 		// i.e. the timer completed, but before we received a conf from the output stream.
       
   219 		if (iExcessData.Length() > 0)
       
   220 			HandleExcessDataL();
       
   221 
       
   222 		// Reset the flag
       
   223 		iTimerCompleted = EFalse;
       
   224 		}
       
   225 	}
       
   226 
       
   227 void CHttpRequestBatcher::HandleExcessDataL()
       
   228 	{
       
   229 	if (iExcessData.Length() > iMaxBufferSize)
       
   230 		{
       
   231 #if defined (_DEBUG) && defined (_LOGGING)
       
   232 		__FLOG_0(_T8("!! Handling excess data - have enough data to fill up another buffer so send it"));
       
   233 #endif
       
   234 
       
   235 		// It's possible that the excess data is larger than the maximum allowable size of the buffer in
       
   236 		// which case this excess data is used to fill up another buffer and a request made.
       
   237 		iDataToSend.Append(iExcessData.Left(iMaxBufferSize));
       
   238 		iOutputStream->SendDataReqL(iDataToSend);
       
   239 		iExcessData.Set(iExcessData.Mid(iMaxBufferSize));
       
   240 		}
       
   241 	else
       
   242 		{
       
   243 		// Not enough data to fill up a buffer therefore store the data
       
   244 		iDataToSend.Append(iExcessData);
       
   245 		iExcessData.Set(KNullDesC8());
       
   246 		iObserver->SendDataCnfL();
       
   247 
       
   248 #if defined (_DEBUG) && defined (_LOGGING)
       
   249 		__FLOG_0(_T8("!! Handling excess data - but not enough data to fill up buffer"));
       
   250 #endif
       
   251 
       
   252 		// start the timer again
       
   253 		StartTimer();			
       
   254 		}
       
   255 	}
       
   256 
       
   257 
       
   258 void CHttpRequestBatcher::SecureClientCnf()
       
   259 	{
       
   260 	iObserver->SecureClientCnf();
       
   261 	}
       
   262 
       
   263 void CHttpRequestBatcher::OutputStreamCloseInd(TInt aError)
       
   264 	{
       
   265 	Cancel();
       
   266 	iObserver->OutputStreamCloseInd(aError);
       
   267 	}
       
   268 
       
   269 void CHttpRequestBatcher::MOutputStreamObserver_Reserved()
       
   270 	{
       
   271 	User::Invariant();
       
   272 	}
       
   273 
       
   274 
       
   275 /*
       
   276  * Methods from CActive
       
   277  */
       
   278 
       
   279 void CHttpRequestBatcher::RunL()
       
   280 	{
       
   281 	if (iDataToSend.Length() > 0)
       
   282 		{
       
   283 #if defined (_DEBUG) && defined (_LOGGING)
       
   284 		__FLOG_0(_T8("!! Timer has completed before buffer has been filled - send request now"));
       
   285 #endif
       
   286 
       
   287 		// Timer has completed before the buffer has been filled, therefore send the request now.
       
   288 		iOutputStream->SendDataReqL(iDataToSend);
       
   289 		}
       
   290 	iTimerCompleted = ETrue;
       
   291 	}
       
   292 
       
   293 void CHttpRequestBatcher::DoCancel()
       
   294 	{
       
   295 	iTimer.Cancel();
       
   296 	}
       
   297 
       
   298 TInt CHttpRequestBatcher::RunError(TInt /*aError*/)
       
   299 	{
       
   300 	// The RunL() cannot leave - nothing to do here.
       
   301 	return KErrNone;
       
   302 	}
       
   303 
       
   304 void CHttpRequestBatcher::OnSendTimeOut()
       
   305 	{
       
   306 	iObserver->OnSendTimeOut();
       
   307 	}
       
   308  
       
   309 TInt CHttpRequestBatcher::SendTimeOutVal()
       
   310 	{
       
   311 	return iObserver->SendTimeOutVal();
       
   312 	}
       
   313 
       
   314 void CHttpRequestBatcher::SetTCPCorking(TBool /* aValue */)
       
   315     {
       
   316     
       
   317     }
       
   318 
       
   319