pkiutilities/ocsp/src/transaction.cpp
changeset 0 164170e6151a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/ocsp/src/transaction.cpp	Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,186 @@
+// Copyright (c) 2001-2009 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:
+// Implementation for OCSP Transaction object.
+// 
+//
+
+#include "transaction.h"
+#include "requestencoder.h"
+#include "responsedecoder.h"
+#include "ocsp.h"
+#include "panic.h"
+
+#include <x509cert.h>
+#include <x509certchain.h>
+
+COCSPTransaction* COCSPTransaction::NewL(const TDesC8& aURI, 
+										 MOCSPTransport& aTransport, const TUint aRetryCount, const TInt aTimeout)
+	{
+	COCSPTransaction* self = new (ELeave) COCSPTransaction(aTransport, aRetryCount, aTimeout);
+	CleanupStack::PushL(self);
+	self->ConstructL(aURI);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+COCSPTransaction::COCSPTransaction(MOCSPTransport& aTransport, const TUint aRetryCount, const TInt aTimeout) :
+	CActive(EPriorityNormal),
+	iTransport(aTransport),
+	iRetryCount(aRetryCount),
+	iTimeout(aTimeout)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+
+void COCSPTransaction::ConstructL(const TDesC8& aURI)
+	{
+	iURI = aURI.AllocL();
+	}
+
+
+COCSPTransaction::~COCSPTransaction()
+	{
+	Cancel();
+	delete iURI;
+	delete iRequestEncoder;
+	delete iResponseDecoder;
+	}
+
+
+// Create the request, then send it off
+void COCSPTransaction::SendRequest(COCSPRequest& aRequest, TRequestStatus& aStatus)
+	{
+	__ASSERT_ALWAYS(!iRequest, Panic(KErrInUse));
+	iClientRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	iRequest = &aRequest;
+	iState = ESendRequest;
+	SetActive();
+
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	}
+
+
+// Safe regardless of whether we have a request outstanding
+void COCSPTransaction::CancelRequest()
+	{
+	Cancel();
+	}
+
+
+COCSPResponse* COCSPTransaction::TakeResponse()
+	{
+	__ASSERT_ALWAYS(iResponseDecoder, Panic(KErrNotReady));
+	return iResponseDecoder->TakeResponse();
+	}
+
+
+void COCSPTransaction::CompleteClient(const TInt aStatus)
+	{
+	User::RequestComplete(iClientRequestStatus, aStatus);
+	}
+
+
+void COCSPTransaction::RunL()
+	{
+	TInt err = iStatus.Int();
+	switch (iState)
+		{
+		case ESendRequest:
+			__ASSERT_ALWAYS(err == KErrNone, Panic(KErrCorrupt));
+			iRequestEncoder = COCSPRequestEncoder::NewL(*iRequest);
+			iTransport.SendRequest(*iURI, iRequestEncoder->Encoding(), iTimeout, iStatus);
+			iState = EFinished;
+			SetActive();			  
+			break;
+
+		case EFinished:
+			{
+			// Depending on the error retry the request
+			// Retry if
+			// 		- More attempts remaining AND 
+			//		- error is OCSP::KErrTransportTimeout OR
+			// 		- error is OCSP::KErrTransportFailure (HTTP response malformed) OR
+			//		- invalid response received (OCSPReponse malformed) OR 
+			//		- OCSPResponseStatus is OCSP::EServerInternalError OR
+			//		- OCSPResponseStatus is OCSP::ETryLater
+			//
+			// We won't retry if 
+			//		- error is OCSP::KErrInvalidURI OR
+			//		- error is OCSP::KErrServerNotFound
+
+			TBool retryNeeded = EFalse;
+			TInt errDecode = KErrNone;
+			if ((err == OCSP::KErrTransportTimeout) || (err == OCSP::KErrTransportFailure))
+				{
+				retryNeeded = ETrue;
+				}
+			else if (err == KErrNone)
+				{
+				TRAP(errDecode, iResponseDecoder = COCSPResponseDecoder::NewL(iTransport.GetResponse()));
+				if ((errDecode == OCSP::EMalformedResponse) || 
+						(errDecode == OCSP::EServerInternalError) || (errDecode == OCSP::ETryLater))
+					{
+					retryNeeded = ETrue;
+					}
+				}
+
+			--iRetryCount;
+			if (retryNeeded && iRetryCount > 0)
+				{
+				__ASSERT_ALWAYS(iResponseDecoder == NULL, Panic(KErrCorrupt));
+				iTransport.SendRequest(*iURI, iRequestEncoder->Encoding(), iTimeout, iStatus);
+				SetActive();
+				}
+			else
+				{
+				// If retry is not needed and there was an error (including +ve) then pass it up else complete normally
+				if (err != KErrNone)
+					{
+					User::Leave(err);
+					}
+				if (errDecode != KErrNone)
+					{
+					User::Leave(errDecode);
+					}
+				CompleteClient(KErrNone);
+				}
+			}
+			break;
+
+		default:
+			Panic(KErrCorrupt);
+		}
+	}
+
+
+TInt COCSPTransaction::RunError(TInt aError)
+	{
+	CompleteClient(aError);
+	return KErrNone;
+	}
+
+
+void COCSPTransaction::DoCancel()
+	{
+	iTransport.CancelRequest();
+	if (iClientRequestStatus)
+		{
+		CompleteClient(KErrCancel);
+		}
+	}
+