void CPjSSLSocket::DoCancel()
{
    /* Operation to be cancelled depends on current state */
    switch (state_) {
    case SSL_STATE_CONNECTING:
	{
	    RSocket &rSock = ((CPjSocket*)sock_)->Socket();

	    rSock.CancelConnect();
	    CleanupSubObjects();
	    state_ = SSL_STATE_NULL;
	}
	break;
    case SSL_STATE_HANDSHAKING:
	{
	    securesock_->CancelHandshake();
	    CleanupSubObjects();
	    state_ = SSL_STATE_NULL;
	}
	break;
    case SSL_STATE_ESTABLISHED:
	securesock_->CancelSend();
	break;
    default:
	break;
    }
}
void CPjSSLSocket::RunL()
{
    switch (state_) {
    case SSL_STATE_CONNECTING:
	if (iStatus != KErrNone) {
	    CleanupSubObjects();
	    state_ = SSL_STATE_NULL;
	    /* Dispatch connect failure notification */
	    if (cb_) (*cb_)(iStatus.Int(), key_);
	} else {
	    RSocket &rSock = ((CPjSocket*)sock_)->Socket();

	    /* Get local addr */
	    rSock.LocalName(local_addr_);
	    
	    /* Prepare and start handshake */
	    securesock_ = CSecureSocket::NewL(rSock, ssl_proto_);
	    securesock_->SetDialogMode(EDialogModeAttended);
	    if (servername_.Length() > 0)
		securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL,
				    servername_);
	    if (ciphers_.Length() > 0)
		securesock_->SetAvailableCipherSuites(ciphers_);

	    // FlushSessionCache() seems to also fire signals to all 
	    // completed AOs (something like CActiveScheduler::RunIfReady())
	    // which may cause problem, e.g: we've experienced that when 
	    // SSL timeout is set to 1s, the SSL timeout timer fires up
	    // at this point and securesock_ instance gets deleted here!
	    // So be careful using this. And we don't think we need it here.
	    //securesock_->FlushSessionCache();

	    securesock_->StartClientHandshake(iStatus);
	    SetActive();
	    state_ = SSL_STATE_HANDSHAKING;
	}
	break;
    case SSL_STATE_HANDSHAKING:
	if (iStatus == KErrNone) {
	    state_ = SSL_STATE_ESTABLISHED;
	} else {
	    state_ = SSL_STATE_NULL;
	    CleanupSubObjects();
	}
	/* Dispatch connect status notification */
	if (cb_) (*cb_)(iStatus.Int(), key_);
	break;
    case SSL_STATE_ESTABLISHED:
	/* Dispatch data sent notification */
	if (cb_) (*cb_)(iStatus.Int(), key_);
	break;
    default:
	pj_assert(0);
	break;
    }
}
EXPORT_C CSecureSocket* CSecureSocket::NewL(MGenericSecureSocket& aSocket,const TDesC& aProtocol)
/** 
 * Creates and returns a pointer to a new secure socket.
 *
 * A reference to a socket derived from MGenericSecureSocket should be passed in, 
 * along with a descriptor that contains the protocol name.
 *
 * @param aSocket	A reference to an MGenericSecureSocket derived object.
 * @param aProtocol	A constant descriptor containing the protocol name.
 * @return 			A pointer to the newly created secure socket, or NULL if the creation failed.
 */
{
	CSecureSocket* self = new(ELeave) CSecureSocket;
	CleanupStack::PushL( self );
	self->ConstructL(aSocket,aProtocol);
	CleanupStack::Pop();
	return self;
}
int CPjSSLSocket::SendSync(const TDesC8 &aDesc, TUint flags)
{
    PJ_UNUSED_ARG(flags);

    PJ_ASSERT_RETURN(state_ == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
    
    TRequestStatus reqStatus;
    securesock_->Send(aDesc, reqStatus, sent_len_);
    User::WaitForRequest(reqStatus);
    
    return PJ_RETURN_OS_ERROR(reqStatus.Int());
}
    void CleanupSubObjects() {
	delete reader_;
	reader_ = NULL;
	if (securesock_) {
	    if (state_ == SSL_STATE_ESTABLISHED)
		securesock_->Close();
	    delete securesock_;
	    securesock_ = NULL;
	}
	if (sock_ != PJ_INVALID_SOCKET) {
	    pj_sock_close(sock_);
	    sock_ = PJ_INVALID_SOCKET;
	}	    
    }
int CPjSSLSocket::Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, 
		       TUint flags)
{
    PJ_UNUSED_ARG(flags);

    PJ_ASSERT_RETURN(state_ == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
    
    if (IsActive())
	return PJ_EBUSY;
    
    cb_ = cb;
    key_ = key;
    
    securesock_->Send(aDesc, iStatus, sent_len_);
    SetActive();
    
    return PJ_EPENDING;
}
TVerdict CTlsTestSection3_1::doTestStepL( )
{
	Log(_L("SSL Socket options test"));

	__UHEAP_MARK;
	// assume that everything passed, unless we leave
	iTestStepResult = EPass;
	TInt error(KErrNone);
    TInt recvBufSize(-1), sendBufSize(-1);
	TInt noDelayEnabled(-1);

	// Create an active scheduler
	CActiveScheduler* myActiveScheduler = new(ELeave) CActiveScheduler();
	CleanupStack::PushL( myActiveScheduler );
	CActiveScheduler::Install( myActiveScheduler );

	// Connect the socket server
	RSocketServ socketServ;
	error = socketServ.Connect();
	TESTEL(error == KErrNone, error);
	CleanupClosePushL(socketServ);

	// Open a socket
	RSocket socket;
	error = socket.Open( socketServ, KAfInet, KSockStream, KProtocolInetTcp );
	TESTEL(error == KErrNone, error);
	CleanupClosePushL(socket);

	Log(_L("Creating a secure socket"));
	CSecureSocket* secureSocket = NULL;
	secureSocket = CSecureSocket::NewL( socket, KDefCfgProtocol );

	// Now do sSetOpt's and GetOpt's at 
	Log(_L("Setting KSORecvBuf to 1000"));
    error = secureSocket->SetOpt(KSORecvBuf, KSOLSocket, 1000);
    TESTEL(error == KErrNone, error);

	Log(_L("Checking KSORecvBuf is set to 1000"));
    error = secureSocket->GetOpt(KSORecvBuf, KSOLSocket, recvBufSize);
    TESTEL(error == KErrNone, error);
    TESTEL(recvBufSize == 1000, recvBufSize);

    error = secureSocket->GetOpt(KSOSendBuf, KSOLSocket, sendBufSize);
    TESTEL(error == KErrNone, error);
	Log(_L("Read sendbuf size of %d"), sendBufSize);

	Log(_L("Read KSoTcpNoDelay of %d"), noDelayEnabled);
    error = secureSocket->GetOpt(KSoTcpNoDelay, KSolInetTcp, noDelayEnabled);
    TESTEL(error == KErrNone, error);

    error = secureSocket->SetOpt(KSoTcpNoDelay, KSolInetTcp, !noDelayEnabled);
    TESTEL(error == KErrNone, error);

	TDialogMode dialogMode = secureSocket->DialogMode();
	Log( _L("Dialog mode setting is: %d"), dialogMode );			

    error = secureSocket->SetDialogMode(EDialogModeUnattended);
    TESTEL(error == KErrNone, error);
    TESTL(secureSocket->DialogMode()==EDialogModeUnattended);
	Log( _L("Dialog mode setting is: %d"), EDialogModeUnattended );			

    error = secureSocket->SetDialogMode(dialogMode);
    TESTEL(error == KErrNone, error);
    TESTL(secureSocket->DialogMode()==dialogMode);
	Log( _L("Dialog mode reset to: %d"), dialogMode );			

	secureSocket->Close();
	delete secureSocket;
	secureSocket = NULL;

	CleanupStack::PopAndDestroy(); // socket
	CleanupStack::PopAndDestroy(); // socketServ

	CActiveScheduler::Install( NULL );
	CleanupStack::PopAndDestroy( myActiveScheduler );

	// unload the securesocket library
	CSecureSocketLibraryLoader::Unload();
	
	__UHEAP_MARKEND;

	return iTestStepResult;
}