/*
* KryptoSesja.h
* Autor: Pawe Gala
*/

#ifndef __KRYPTOSESJA_H__
#define __KRYPTOSESJA_H__

#include <e32base.h>
#include "KryptografAsync.h"


class CKryptoSerwer;

class CKryptoSesja : public CSession2
    {
    public:        // Konstruktory dwufazowe i destruktor
        static CKryptoSesja* NewL( CKryptoSerwer& aSerwer );
        static CKryptoSesja* NewLC( CKryptoSerwer& aSerwer );

        virtual ~CKryptoSesja();

    public:        // Odziedziczone z CSession2
        void ServiceL( const RMessage2& aMessage );
        
    private:    // Konstruktory pierwszej i drugiej fazy
        CKryptoSesja( CKryptoSerwer& aSerwer );
        void ConstructL();

    private:
        void SzyfrujSyncL( const RMessage2& aMessage );
        void SzyfrujAsyncL( const RMessage2& aMessage );
        void AnulujSzyfrowanieL( const RMessage2& aMessage );
        void DeszyfrujSyncL( const RMessage2& aMessage );
        void DeszyfrujAsyncL( const RMessage2& aMessage );
        void AnulujDeszyfrowanieL( const RMessage2& aMessage );
    
        void SpanikujKlienta( const RMessage2& aMessage, TInt aNrPaniki ) const;

    private:    // Pola
        CKryptoSerwer& iKryptoSerwer;
        
        // Kryptograf dla synchronicznych usug szyfrowania
        TKryptograf iKryptograf;
        // Aby moliwe byo rwnoczesne wykonywanie usug szyfrowania
        // i deszyfrowania, potrzebujemy dwch obiektw kryptografa 
        // asynchronicznego.
        CKryptografAsync* iKASzyf;
        CKryptografAsync* iKADeszyf;
    };

#endif // __KRYPTOSESJA_H__


/*
* KryptoSesja.cpp
* Autor: Pawe Gala
*/

#include <e32svr.h>

#include "KryptoSesja.h"
#include "KryptoWspolne.h"
#include "KryptoSerwer.h"


CKryptoSesja* CKryptoSesja::NewL( CKryptoSerwer& aSerwer )
    {
    CKryptoSesja* self = CKryptoSesja::NewLC( aSerwer );
    CleanupStack::Pop( self );
    return self;
    }

CKryptoSesja* CKryptoSesja::NewLC( CKryptoSerwer& aSerwer )
    {
    CKryptoSesja* self = new( ELeave ) CKryptoSesja( aSerwer );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

void CKryptoSesja::ConstructL()
    {
    iKASzyf = new( ELeave ) CKryptografAsync();
    iKADeszyf = new( ELeave ) CKryptografAsync();
    
    iKryptoSerwer.InkrementujLicznikSesji();
    }

CKryptoSesja::CKryptoSesja( CKryptoSerwer& aSerwer ) : iKryptoSerwer( aSerwer )
    {
    }

CKryptoSesja::~CKryptoSesja()
    {
    delete iKASzyf;
    delete iKADeszyf;
    
    iKryptoSerwer.DekrementujLicznikSesji();
    }

void CKryptoSesja::ServiceL( const RMessage2& aMessage )
    {
    switch ( aMessage.Function() )
        {
        case ESzyfrujSync:
            SzyfrujSyncL( aMessage );
            break;
    
        case ESzyfrujAsync:
            SzyfrujAsyncL( aMessage );
            break;
        
        case EAnulujSzyfrowanie:
            AnulujSzyfrowanieL( aMessage );
            break;
            
        case EDeszyfrujSync:
            DeszyfrujSyncL( aMessage );
            break;
    
        case EDeszyfrujAsync:
            DeszyfrujAsyncL( aMessage );
            break;
    
        case EAnulujDeszyfrowanie:
            AnulujDeszyfrowanieL( aMessage );
            break;

        default:
            SpanikujKlienta( aMessage, ENieprawidlowyIdFunkcji );
        }
    }

void CKryptoSesja::SzyfrujSyncL( const RMessage2& aMessage )
    {
    HBufC8* daneDoSzyf = HBufC8::NewLC( aMessage.GetDesLength( 0 ) );
    TPtr8 daneDoSzyfWsk = daneDoSzyf->Des();
    HBufC8* daneZaszyf = HBufC8::NewLC( aMessage.GetDesMaxLengthL( 1 ) );
    TPtr8 daneZaszyfWsk = daneZaszyf->Des();
    
    aMessage.ReadL( 0, daneDoSzyfWsk, 0 );
    
    User::LeaveIfError( iKryptograf.Szyfruj( daneDoSzyfWsk, daneZaszyfWsk ) );
    aMessage.WriteL( 1, daneZaszyfWsk, 0 );
    aMessage.Complete( KErrNone );
    
    CleanupStack::PopAndDestroy( daneZaszyf );
    CleanupStack::PopAndDestroy( daneDoSzyf );
    }

void CKryptoSesja::SzyfrujAsyncL( const RMessage2& aMessage )
    {
    TInt blad = iKASzyf->Szyfruj( aMessage );
    // Jeeli blad == KErrNone, wwczas iKASzyf odpowiada za wywoanie metody
    // Complete() na komunikacie aMessage.
    
    if( blad )
        {
        aMessage.Complete( blad );
        }
    }

void CKryptoSesja::AnulujSzyfrowanieL( const RMessage2& aMessage )
    {
    iKASzyf->Cancel();
    }

void CKryptoSesja::DeszyfrujSyncL( const RMessage2& aMessage )
    {
    HBufC8* daneZaszyf = HBufC8::NewLC( aMessage.GetDesLength( 0 ) );
    TPtr8 daneZaszyfWsk = daneZaszyf->Des();
    HBufC8* daneOdszyf = HBufC8::NewLC( aMessage.GetDesMaxLengthL( 1 ) );
    TPtr8 daneOdszyfWsk = daneOdszyf->Des();
    
    aMessage.ReadL( 0, daneZaszyfWsk, 0 );
    
    User::LeaveIfError( iKryptograf.Deszyfruj( daneZaszyfWsk, daneOdszyfWsk ) );
    aMessage.WriteL( 1, daneOdszyfWsk, 0 );
    aMessage.Complete( KErrNone );
    
    CleanupStack::PopAndDestroy( daneOdszyf );
    CleanupStack::PopAndDestroy( daneZaszyf );
    }

void CKryptoSesja::DeszyfrujAsyncL( const RMessage2& aMessage )
    {
    TInt blad = iKADeszyf->Deszyfruj( aMessage );
    // Jeeli blad == KErrNone, wwczas iKADeszyf odpowiada za wywoanie metody
    // Complete() na komunikacie aMessage.
    
    if( blad )
        {
        aMessage.Complete( blad );
        }
    }

void CKryptoSesja::AnulujDeszyfrowanieL( const RMessage2& aMessage )
    {
    iKADeszyf->Cancel();
    }
    
void CKryptoSesja::SpanikujKlienta( const RMessage2& aMessage, TInt aNrPaniki ) const
    {
    aMessage.Panic( KKryptoSerwerPanika, aNrPaniki );
    }
